Apollo-link-rest: REST 응닡이 λΉ„μ–΄μžˆλŠ” 경우 였λ₯˜

에 λ§Œλ“  2018λ…„ 05μ›” 07일  Β·  18μ½”λ©˜νŠΈ  Β·  좜처: apollographql/apollo-link-rest


μ„±κ³΅ν•˜λ©΄ 204 "μ½˜ν…μΈ  μ—†μŒ"μƒνƒœλ‘œ μ‘λ‹΅ν•˜λŠ” λ³€ν˜• μš”μ²­μ΄ μžˆμŠ΅λ‹ˆλ‹€. apollo-link-error와 κ²°ν•©ν•˜λ©΄ μ§€μ†μ μœΌλ‘œ λ„€νŠΈμ›Œν¬ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€ : Unexpected end of JSON input .

apollo-link-restκ°€ μ‘λ‹΅μ˜ 빈 본문을 ꡬ문 λΆ„μ„ν•˜λ €λŠ” κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.

이것을 μ™„ν™”ν•˜λŠ” 방법에 λŒ€ν•œ 아이디어가 μžˆμŠ΅λ‹ˆκΉŒ? BTW SharePoint REST API와 ν†΅μ‹ ν•˜λ €κ³ ν•˜λ―€λ‘œ μ„œλ²„ 응닡을 μ‘°μ •ν•  μˆ˜μžˆλŠ” 방법이 λ§Žμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

빈 응닡을 μ²˜λ¦¬ν•˜λŠ” 방법을 apollo-link-rest에 μ•Œλ¦¬λŠ” 방법이 μžˆμ–΄μ•Όν•©λ‹ˆλ‹€.

λ‚΄ λŒμ—°λ³€μ΄ 호좜 :

                  <Mutation mutation={M_WRITE_PROJECT_DETAILS}>
                    {(writeProjectDetails, { data }) => (
                      <Form.Button
                        content="Save"
                        onClick={() => {
                          const token = localStorage.getItem("token");
                          writeProjectDetails({
                            variables: {
                              projectId: project.Id,
                              input: {
                                __metadata: {
                                  type: "SP.Data.ProjectListItem"
                                },
                                Title: project.Title
                              }
                            },
                            context: {
                              headers: {
                                "X-RequestDigest": token,
                                "X-HTTP-Method": "MERGE",
                                "IF-MATCH": "*"
                              }
                            }
                          });
                        }}
                      />
                    )}
                  </Mutation>

ν•΄λ‹Ήν•˜λŠ” gql 쿼리 :

const M_WRITE_PROJECT_DETAILS = gql`
  mutation writeToSPList($projectId: String, $input: String) {
    writeToSPList(projectId: $projectId, input: $input)
      @rest(
        type: "Project"
        path: "/web/lists/GetByTitle('Projects')/items(:projectId)"
        method: "POST"
      ) {
      NoResponse
    }
  }
`;

"NoResponse"λŠ” 응닡이 μ—†κΈ° λ•Œλ¬Έμ— λΆ„λͺ…νžˆ _null_μ΄μ§€λ§Œ 응닡 ν•„λ“œμ—†μ΄ λ³€ν˜•μ„ 보낼 수 μ—†μŠ΅λ‹ˆλ‹€.

enhancementπŸ’‘ feature help wanted πŸ›  question❔

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

빈 본문의 μ—…μŠ€νŠΈλ¦Ό GraphQL 해석이 μž‘λ™ν•˜λ €λ©΄ {} λ₯Ό λ°˜ν™˜ν•΄μ•Όν•©λ‹ˆλ‹€.

data: {
  __typename: "...",
  NoResponse: null,
}

"두 행동이 λͺ¨λ‘ 지원 될 수 μžˆμŠ΅λ‹ˆκΉŒ?"라고 λ§ν•˜λ©΄ 204 μƒνƒœ μ½”λ“œλ₯Όλ³΄κ³  헀더λ₯Όλ³΄κ³  μžˆλ‹€λŠ” λœ»μž…λ‹ˆκΉŒ? Content-Length κ°€ μ‹€μ œλ‘œ μ‘΄μž¬ν•˜κ³  0 μžˆμ„ λ•Œμ΄λ₯Ό 빈 본문의 또 λ‹€λ₯Έ ν‘œμ‹œλ‘œ μ·¨ν•˜κ³  기본값을 λ°˜ν™˜ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이전에 Content-Type 헀더λ₯Ό μ œμ•ˆν–ˆμ§€λ§Œ json μ΄μ™Έμ˜ κ²ƒμœΌλ‘œ μ„€μ •λ˜μ—ˆμ„ λ•Œ μˆ˜ν–‰ν•΄μ•Ό ν•  μž‘μ—…μ— λŒ€ν•΄ μ •ν™•νžˆ μ•Œ 수 μ—†μŠ΅λ‹ˆλ‹€. 이 헀더λ₯Ό ν•΄μ„ν•˜λ €λ©΄ μ œμ•ˆ 된 bodySerializer κ³Ό μœ μ‚¬ν•œ responseSerializer ꡬ성 μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ μˆ˜ν–‰ν•΄μ•Ό ν•  κ²ƒμž…λ‹ˆλ‹€. 그것은 μ•„λ§ˆλ„ κ³Όμž‰μ΄λ©° 특히 빈 λ³Έλ¬Έ 문제λ₯Ό ν•΄κ²°ν•˜μ§€ λͺ»ν•  κ²ƒμž…λ‹ˆλ‹€.

204 및 Content-Length κ΅¬ν˜„μ„ μˆ˜ν–‰ν•˜κ²Œλ˜μ–΄ κΈ°μ©λ‹ˆλ‹€.

λͺ¨λ“  18 λŒ“κΈ€

@isopterix- μ§€κΈˆ λ‹Ήμž₯이 문제λ₯Ό μ‰½κ²Œ ν•΄κ²°ν•  방법이 μ—†λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. -λ‚΄ 초기 생각은 Fetchλ₯Ό λž˜ν•‘ν•˜κ³  204 개의 응닡 본문을 {} λŒ€μ²΄ν•˜λŠ” μ‚¬μš©μž 지정 Fetch κ΅¬ν˜„μ„ μ œκ³΅ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€

@isopterix μ•„λž˜ ν…ŒμŠ€νŠΈλ‘œμ΄ 문제λ₯Ό μž¬ν˜„ν•˜λ €κ³ ν–ˆμ§€λ§Œ ν…ŒμŠ€νŠΈλŠ” 빈 본문에 ν†΅κ³Όν–ˆμŠ΅λ‹ˆλ‹€. 본문이 빈 λ¬Έμžμ—΄ 인 경우 fetch response.json() κ°€ {} λ°˜ν™˜ν•˜λŠ” κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€. 였λ₯˜κ°€ λ°œμƒν•˜λŠ” μœ„μΉ˜λ₯Ό ν™•μΈν•˜κΈ° μœ„ν•΄ 라이브 μ„€μ •μ—μ„œ 더 μžμ„Ένžˆ 좔적 ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

  describe('response parsing', () => {
    it('supports empty response bodies', async () => {
      expect.assertions(1);

      const link = new RestLink({ uri: '/api' });

      fetchMock.post('/api/posts', {
        status: 204,
        body: '',
      });

      const mutation = gql`
        mutation postEmptyResponse($input: String!) {
          newPost(input: $input)
            @rest(type: "Post", path: "/posts", method: "POST") {
            NoResponse
          }
        }
      `;
      const {data} = await makePromise<Result>(
        execute(link, {
          operationName: 'postEmptyResponse',
          query: mutation,
          variables: { input: 'Love apollo' },
        }),
      );

      expect(data).toEqual({
        newPost: {
          NoResponse: null,
          __typename: 'Post',
        }
      });
    });
  });

@isopterix λŠ” λ‚΄ λ§ˆμ§€λ§‰ λŒ“κΈ€μ„ μ‹ κ²½

빈 본문을 감지 ν•  λ•Œ λ‚΄κ°€ λ³΄λŠ” ν•œ 가지 λ¬Έμ œλŠ” res.json() λ˜λŠ” res.text() λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•Šκ³  본문에 무엇이 μžˆλŠ”μ§€ μ•Œ μˆ˜μžˆλŠ” ν™•μ‹€ν•œ 방법이 μ—†μœΌλ©° 항상 두 가지 λͺ¨λ‘λ₯Ό ν˜ΈμΆœν•˜λŠ” κ²½μš°λ„ μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λΆˆν•„μš”ν•œ. 그렇지 μ•ŠμœΌλ©΄ Content-Length 헀더λ₯Ό λ³Ό 수 μžˆμ§€λ§Œ 항상 μ‹ λ’°ν•  수 μžˆλŠ”μ§€ ν™•μ‹€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 또 λ‹€λ₯Έ μ˜΅μ…˜μ€ Content-Type κ°€ application/json 인 κ²½μš°μ—λ§Œ JSON을 ꡬ문 λΆ„μ„ν•˜λŠ” κ²ƒμ΄μ§€λ§Œ 일뢀 APIλŠ” λͺ¨λ“  응닡과 빈 204 응닡에 λŒ€ν•΄ ν•΄λ‹Ή 헀더λ₯Ό κ³΅ν†΅μœΌλ‘œ μ„€μ •ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

λ‚˜λ¨Έμ§€ λ§ν¬λŠ” 300 μ΄μƒμ˜ μƒνƒœ μ½”λ“œμ—μ„œ networkError λ₯Ό μƒμ„±ν•˜λ―€λ‘œ 응닡 ꡬ문 뢄석은 2xx μƒνƒœ μ½”λ“œλ₯Ό μ˜¬λ°”λ₯΄κ²Œ 처리 ν•  μˆ˜μžˆμ„λ§ŒνΌ μΆ©λΆ„νžˆ μ „λ¬Έν™”λ˜μ–΄μ•Όν•©λ‹ˆλ‹€. λ‹€μŒκ³Ό 같이 ν•©λ¦¬μ μœΌλ‘œ μ˜ˆμƒ ν•  μˆ˜μžˆλŠ” 것듀 쀑 :

  • 200 OK
  • 201 생성됨
  • 202 수락 됨
  • 204 λ‚΄μš© μ—†μŒ
  • (λ‹€λ₯Έ μ‚¬λžŒ?)

204 응닡은 본문이 λΉ„μ–΄μžˆλŠ” μœ μΌν•œ μ‘λ‹΅μ΄μ–΄μ•Όν•©λ‹ˆλ‹€. μƒνƒœ μ½”λ“œλ₯Ό κ²€μ‚¬ν•˜κ³  204 일 λ•Œ κΈ°λ³Έ {} λ°˜ν™˜ν•˜λŠ” μ˜΅μ…˜μΌκΉŒμš”? 맀우 ꡬ체적인 엣지 μΌ€μ΄μŠ€μ— λŒ€ν•œ ν…ŒμŠ€νŠΈμ΄κΈ°λŠ”ν•˜μ§€λ§Œ λΌμ΄λΈŒλŸ¬λ¦¬κ°€ HTTP ν‘œμ€€μ„λ³΄λ‹€ 잘 μ€€μˆ˜ν•˜λ„λ‘ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

@fbartho μ΄λŸ¬ν•œ μ ‘κ·Ό 방식 쀑 ν•˜λ‚˜λ₯Ό μ„ ν˜Έν•©λ‹ˆκΉŒ? 이 μ˜΅μ…˜ 쀑 ν•˜λ‚˜ λ˜λŠ” κ·Έ 쑰합이 ν•©λ¦¬μ μœΌλ‘œ 듀리면 PR을 ν•  κ²ƒμž…λ‹ˆλ‹€.

여기에 쀑간 길이 μžˆμ„κΉŒμš”? 두 가지 행동을 λͺ¨λ‘ 지원할 수 μžˆμŠ΅λ‹ˆκΉŒ?

μ €λŠ” 204λ₯Ό 기본적으둜 {}둜 ν•΄μ„ν•˜λŠ” 것을 λ§€μš°μ§€μ§€ν•©λ‹ˆλ‹€. λ˜λŠ” "null"이 JSON의 λ‚΄μš©μ΄μ—†λŠ” μ˜λ―Έμ— ν•΄λ‹Ήν•˜λŠ” null둜 κ°„μ£Όλ©λ‹ˆκΉŒ?

빈 본문의 μ—…μŠ€νŠΈλ¦Ό GraphQL 해석이 μž‘λ™ν•˜λ €λ©΄ {} λ₯Ό λ°˜ν™˜ν•΄μ•Όν•©λ‹ˆλ‹€.

data: {
  __typename: "...",
  NoResponse: null,
}

"두 행동이 λͺ¨λ‘ 지원 될 수 μžˆμŠ΅λ‹ˆκΉŒ?"라고 λ§ν•˜λ©΄ 204 μƒνƒœ μ½”λ“œλ₯Όλ³΄κ³  헀더λ₯Όλ³΄κ³  μžˆλ‹€λŠ” λœ»μž…λ‹ˆκΉŒ? Content-Length κ°€ μ‹€μ œλ‘œ μ‘΄μž¬ν•˜κ³  0 μžˆμ„ λ•Œμ΄λ₯Ό 빈 본문의 또 λ‹€λ₯Έ ν‘œμ‹œλ‘œ μ·¨ν•˜κ³  기본값을 λ°˜ν™˜ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이전에 Content-Type 헀더λ₯Ό μ œμ•ˆν–ˆμ§€λ§Œ json μ΄μ™Έμ˜ κ²ƒμœΌλ‘œ μ„€μ •λ˜μ—ˆμ„ λ•Œ μˆ˜ν–‰ν•΄μ•Ό ν•  μž‘μ—…μ— λŒ€ν•΄ μ •ν™•νžˆ μ•Œ 수 μ—†μŠ΅λ‹ˆλ‹€. 이 헀더λ₯Ό ν•΄μ„ν•˜λ €λ©΄ μ œμ•ˆ 된 bodySerializer κ³Ό μœ μ‚¬ν•œ responseSerializer ꡬ성 μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ μˆ˜ν–‰ν•΄μ•Ό ν•  κ²ƒμž…λ‹ˆλ‹€. 그것은 μ•„λ§ˆλ„ κ³Όμž‰μ΄λ©° 특히 빈 λ³Έλ¬Έ 문제λ₯Ό ν•΄κ²°ν•˜μ§€ λͺ»ν•  κ²ƒμž…λ‹ˆλ‹€.

204 및 Content-Length κ΅¬ν˜„μ„ μˆ˜ν–‰ν•˜κ²Œλ˜μ–΄ κΈ°μ©λ‹ˆλ‹€.

μ§€κΈˆκΉŒμ§€ μ΄μ „μ˜ 쑰언을 λ”°λžκ³  204 응닡을 μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ μ‚¬μš©μž 지정 κ°€μ Έ 였기λ₯Ό κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ μ ˆν•œ 응닡을 λ°›κΈ°κ°€ μ–΄λ €μ› μŠ΅λ‹ˆλ‹€. 이 κΈ°λŠ₯을 μ¦‰μ‹œ μ‚¬μš©ν•  μˆ˜μžˆλŠ” μ˜΅μ…˜μ΄ 있으면 λ©‹μ§ˆ κ²ƒμž…λ‹ˆλ‹€.

λΆˆν–‰νžˆλ„ λ‚˜λŠ” μ—¬μ „νžˆ JS 세계λ₯Ό νƒμƒ‰ν•˜λŠ” 방법을 배우고 μžˆμŠ΅λ‹ˆλ‹€.

# 111을 톡해 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€!

단! λŒ€λ‹¨νžˆ κ°μ‚¬ν•©λ‹ˆλ‹€.

이제 μž‘μ€ λ¬Έμ œκ°€ ν•˜λ‚˜λ§Œ 남아 μžˆμŠ΅λ‹ˆλ‹€. :) λ‚΄ μž„μ‹œ μ†”λ£¨μ…˜μ„ 개발 ν•œ 직후 λŒ€μƒ SharePoint Server의 REST API에 또 λ‹€λ₯Έ λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. ν•­λͺ©μ„ μ‚­μ œν•˜λ©΄ 200 개의 응닡이 ν‘œμ‹œλ©λ‹ˆλ‹€. λ³Έλ¬Έ λ‚΄μš© μ—†μŒ :)

즉, "NoResponse"νƒœκ·Έλ‘œ μ‘λ‹΅ν•˜λŠ” λ³Έλ¬Έ λ‚΄μš©μ΄μ—†λŠ” 경우 λ™μž‘μ„ 잠재적으둜 μΌλ°˜ν™” ν•  수 μžˆμŠ΅λ‹ˆκΉŒ? λ‚΄κ°€ μ°©κ°ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ νŒ¨μΉ˜λŠ” ν˜„μž¬ 204 특수 μ‚¬λ‘€λ§Œμ„ 닀룬닀.

@isopterix μ„œλ²„κ°€ Content-Length λ₯Ό 0으둜 μ˜¬λ°”λ₯΄κ²Œ μ„€μ •ν•˜λ©΄ 200 개의 μ‘λ‹΅μ—μ„œλ„ μž‘λ™ν•΄μ•Όν•˜λ©°, κ·Έ μ˜λ„λ„ ν™•μΈν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

νšŒμ „μ„ κΈ°λŒ€ν•©λ‹ˆλ‹€.

λ‚΄μš©μ΄ λΉ„μ–΄μžˆλŠ” 성곡적인 응닡을 μ²˜λ¦¬ν•©λ‹ˆκΉŒ? λ‚΄μš©μ΄μ—†λŠ” 200처럼?

예. 이λ₯Ό μœ„ν•΄ 병합 된 μˆ˜μ • ν”„λ‘œκ·Έλž¨μ€ 204 μƒνƒœ λ˜λŠ” Content-Length: 0 헀더λ₯Ό ν™•μΈν•˜κ³  빈 개체λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

Content-Length ν—€λ”κ°€μ—†λŠ” 200 개의 빈 μ‘λ‹΅μ΄μžˆλŠ” 경우 본문이이 검사λ₯Ό μœ„ν•΄ ꡬ문 λΆ„μ„λ˜μ§€ μ•ŠμœΌλ―€λ‘œ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

@isopterix 이것이 μž‘λ™ν•˜λŠ”μ§€ 확인할 수 μžˆμŠ΅λ‹ˆκΉŒ? λ‚˜λŠ” 200 μƒνƒœμ™€ Content-Length: 0 μ„μ£ΌλŠ” λŒμ—°λ³€μ΄λ₯Ό μ‹œλ„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ—¬μ „νžˆ Network error: Unexpected end of JSON input λ°›κ³  μžˆμŠ΅λ‹ˆλ‹€. 버전 0.7.0을 μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

λ‚΄ λΈŒλΌμš°μ €κ°€ μ‹€μ œλ‘œ 헀더λ₯Ό ν‘œμ‹œν•˜λŠ” λ™μ•ˆ apollo-link-rest 디버깅 ν•  λ•Œ 응닡 헀더가 λΉ„μ–΄μžˆλŠ” 것을 ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€. apollo-link-rest λŠ” 응닡 객체의 헀더λ₯Ό μ‘°μž‘ / μž¬μ„€μ •ν•©λ‹ˆκΉŒ?

Apollo-link-restλŠ” @dljcollette 응닡 헀더λ₯Ό μ‘°μž‘ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€! λ„μ›€μ΄λ˜λŠ” 희망

λ‚˜λŠ” 같은 였λ₯˜λ₯Ό λ§Œλ‚œλ‹€

본문이 λΉ„μ–΄μžˆλŠ” μƒνƒœ 200에 λŒ€ν•œ ν•΄κ²° 방법이 μžˆμŠ΅λ‹ˆκΉŒ?

@thomaszdxsn 이λ₯Ό μˆ˜μš©ν•˜λŠ” μœ μΌν•œ 방법은 res.json() λŒ€μ‹  res.text() μ‚¬μš©ν•˜κ³  JSON.parse() ꡬ문 λΆ„μ„ν•˜κΈ° 전에 μœ νš¨ν•œ JSON을 ν™•μΈν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 즉, 슀트리밍 JSON ꡬ문 뢄석이 λŠμŠ¨ν•΄ μ§€λ―€λ‘œ μˆ˜ν–‰ ν•  κ°€λŠ₯성이 μ—†μŠ΅λ‹ˆλ‹€.

κ°€μž₯ 쒋은 해결책은 APIλ₯Ό λ³€κ²½ν•˜μ—¬ 본문이 λΉ„μ–΄μžˆμ„ λ•Œ 의미 상 μ˜¬λ°”λ₯Έ μƒνƒœ μ½”λ“œ 204λ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜ 200 응닡 본문에 무언가λ₯Ό λ°˜ν™˜ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 응닡 본문에 μœ νš¨ν•œ JSON 인 것이 있으면 빈 JSON 인코딩 κ°œμ²΄λ„ μž‘λ™ ν•  것이라고 μƒκ°ν•©λ‹ˆλ‹€.

μ‹€μ œλ‘œ APIλ₯Ό λ³€κ²½ν•  μˆ˜μ—†λŠ” 경우 μ‚¬μš©μž 지정 fetch ν•¨μˆ˜λ₯Ό apollo-link-rest 에 전달할 수 μžˆμŠ΅λ‹ˆλ‹€. κ²°κ΅­ ALR을 μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ λ°˜ν™˜ν•˜κΈ° 전에 응닡을 κ²€μ‚¬ν•˜κ³  λ³€κ²½ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 해킹이 될 수 μžˆμ§€λ§Œ λ‹Ήμ‹ μ—κ²ŒλŠ” νš¨κ³Όκ°€μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

λ˜λŠ” λ‹€μ‹œ APIκ°€ 응닡에 Content-length: 0 헀더λ₯Ό λ°˜ν™˜ν•˜λŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰