Apollo-link-rest: Terjadi error saat respons REST kosong

Dibuat pada 7 Mei 2018  ·  18Komentar  ·  Sumber: apollographql/apollo-link-rest


Saya memiliki permintaan mutasi yang bila berhasil merespons dengan status 204 "Tidak ada konten". Ketika digabungkan dengan apollo-link-error, saya terus-menerus mendapatkan error jaringan: Akhir input JSON yang tidak terduga .

Tampaknya apollo-link-rest mencoba mengurai isi respons yang kosong.

Ada ide bagaimana mengurangi ini? BTW Saya mencoba berbicara dengan api REST SharePoint, jadi tidak banyak yang bisa saya lakukan untuk mengubah respons server.

Harus ada cara untuk memberi tahu apollo-link-rest cara menangani respons kosong ...

Panggilan mutasi saya:

                  <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>

Kueri gql terkait:

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" jelas _null_ karena tidak ada respons, tetapi sekali lagi saya tidak dapat mengirim mutasi tanpa kolom respons ... kecuali saya melewatkan sesuatu.

enhancement💡 feature help wanted 🛠 question❔

Komentar yang paling membantu

Saya pikir agar interpretasi GraphQL hulu dari badan kosong berfungsi, kita harus mengembalikan {} yang kemudian akan menghasilkan

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

Saat Anda mengatakan "Bisakah kedua perilaku didukung?" maksud Anda melihat kode status 204 dan melihat header? Saya kira ketika Content-Length benar-benar ada dan juga 0 maka kita bisa menganggapnya sebagai indikasi lain dari tubuh kosong dan mengembalikan default.

Meskipun saya mengusulkan header Content-Type sebelumnya, saya sebenarnya tidak begitu jelas tentang apa yang harus dilakukan ketika diatur ke sesuatu selain json . Saya pikir jika tajuk ini akan ditafsirkan mungkin perlu dilakukan dengan opsi konfigurasi responseSerializer mirip dengan bodySerializer diusulkan. Itu mungkin berlebihan, dan tidak akan membahas masalah tubuh kosong secara khusus.

Saya senang melakukan implementasi 204 dan Panjang Konten.

Semua 18 komentar

@isopterix - Saya rasa kita tidak memiliki cara mudah untuk mengatasinya sekarang. - Pikiran awal saya adalah merekomendasikan Anda membungkus Fetch & memberikan implementasi Fetch kustom yang menggantikan isi respons 204 dengan {} - Saya pikir tanpa membangun fitur yang lebih baik, itulah satu-satunya cara saya dapat melakukan ini hari ini!

@isopterix Saya mencoba mereproduksi masalah ini dengan tes di bawah, tetapi tes lolos untuk tubuh kosong. Tampaknya mengambil response.json() mengembalikan {} ketika badan adalah string kosong. Bisakah Anda mencoba melacak ini lebih dekat dalam pengaturan langsung Anda untuk melihat di mana kesalahan terjadi?

  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 sudahlah komentar terakhir saya. Tampaknya penerapan browser kurang memaafkan dibandingkan lingkungan pengujian.

Satu masalah yang saya lihat dengan mendeteksi tubuh kosong adalah bahwa tidak ada cara pasti untuk mengetahui apa yang ada di dalam tubuh tanpa memanggil res.json() atau res.text() , dan selalu memanggil keduanya untuk berjaga-jaga juga. mubazir. Jika tidak, orang mungkin melihat header Content-Length , tetapi saya tidak terlalu yakin apakah itu akan selalu dapat diandalkan. Pilihan lain hanya akan mengurai JSON jika Content-Type adalah application/json , tetapi juga dapat dibayangkan bahwa beberapa API mungkin menyetel header yang sama untuk semua tanggapan dan bahkan pada tanggapan 204 kosong.

Karena tautan lainnya menghasilkan networkError pada kode status apa pun di atas 300, penguraian respons hanya perlu cukup terspesialisasi untuk menangani kode status 2xx dengan benar. Dari yang mungkin diharapkan untuk ditemui, adalah:

  • 200 OK
  • 201 Dibuat
  • 202 Diterima
  • 204 Tidak Ada Konten
  • (salah satu dari yang lain?)

204 tanggapan harus menjadi satu-satunya yang memiliki tubuh kosong. Apakah ini pilihan untuk memeriksa kode status dan mengembalikan default {} ketika 204? Meskipun ini akan menjadi tes untuk kasus edge yang sangat spesifik, itu akan membuat perpustakaan lebih sesuai dengan standar HTTP yang tampaknya merupakan hal yang baik.

@fbartho, maukah Anda memilih salah satu dari pendekatan ini? Saya akan membuat PR jika salah satu dari opsi ini, atau kombinasinya, terdengar masuk akal.

Mungkin ada jalan tengah di sini? Bisakah kedua perilaku itu didukung?

Saya cukup mendukung untuk menafsirkan 204 sebagai {} secara default sendiri, atau sebagai "null" adalah null yang setara semantik dari tidak ada konten di JSON?

Saya pikir agar interpretasi GraphQL hulu dari badan kosong berfungsi, kita harus mengembalikan {} yang kemudian akan menghasilkan

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

Saat Anda mengatakan "Bisakah kedua perilaku didukung?" maksud Anda melihat kode status 204 dan melihat header? Saya kira ketika Content-Length benar-benar ada dan juga 0 maka kita bisa menganggapnya sebagai indikasi lain dari tubuh kosong dan mengembalikan default.

Meskipun saya mengusulkan header Content-Type sebelumnya, saya sebenarnya tidak begitu jelas tentang apa yang harus dilakukan ketika diatur ke sesuatu selain json . Saya pikir jika tajuk ini akan ditafsirkan mungkin perlu dilakukan dengan opsi konfigurasi responseSerializer mirip dengan bodySerializer diusulkan. Itu mungkin berlebihan, dan tidak akan membahas masalah tubuh kosong secara khusus.

Saya senang melakukan implementasi 204 dan Panjang Konten.

Sejauh ini saya mengikuti saran sebelumnya dan menerapkan pengambilan khusus untuk menangani respons 204. Tetapi saya mengalami kesulitan untuk mendapatkan tanggapan yang tepat kembali. Memiliki opsi untuk mengeluarkan fungsi ini dari kotak akan luar biasa.

Sayangnya, saya masih belajar bagaimana menavigasi dunia JS ...

Diperbaiki melalui # 111!

Manis! Terima kasih banyak.

Sekarang, hanya ada satu masalah kecil yang masih tersisa :) Tepat setelah saya menemukan solusi sementara saya sendiri, saya mengalami masalah lain lagi dengan REST API target SharePoint Server saya ... Jika Anda menghapus entri, Anda mendapatkan 200 respons tanpa konten tubuh :)

Bisakah kita menggeneralisasi perilaku secara potensial, yaitu jika tidak ada respons konten tubuh dengan tag "NoResponse"? Jika saya tidak salah, tambalan saat ini hanya membahas 204 kasus khusus.

@isopterix Jika server mengeset Content-Length menjadi nol dengan benar, ia akan bekerja bahkan pada 200 respon, maksudnya adalah untuk memeriksanya juga.

Berharap untuk mencobanya.

Apakah ini mencakup respons yang berhasil dengan konten kosong? Seperti 200 tanpa konten?

Iya. Perbaikan yang digabungkan untuk pemeriksaan ini untuk status 204 atau Content-Length: 0 header dan mengembalikan objek kosong.

Jika Anda memiliki 200 respon kosong tanpa header Content-Length itu tidak akan bekerja karena body tidak diurai untuk pemeriksaan ini.

@isopterix apakah Anda dapat mengonfirmasi bahwa ini berfungsi? Saya mencoba melakukan mutasi yang memberi saya status 200 dan Content-Length: 0 . Namun, saya masih mendapatkan Network error: Unexpected end of JSON input . Saya menggunakan versi 0.7.0.

Saya melihat bahwa header respons kosong saat men-debug apollo-link-rest , sedangkan browser saya sebenarnya menampilkan header. Apakah apollo-link-rest memanipulasi / mengatur ulang header di objek respons?

Apollo-link-rest tidak memanipulasi header tanggapan @dljcollette! Semoga membantu

Saya menemui kesalahan yang sama

apakah ada solusi untuk status 200 dengan badan kosong?

@thomaszdxsn satu-satunya cara untuk mengakomodasi itu adalah dengan menggunakan res.text() alih-alih res.json() dan periksa JSON yang valid sebelum mem-parsing dengan JSON.parse() . Ini berarti Anda kehilangan penguraian JSON streaming dan karena itu kemungkinan besar tidak akan dilakukan.

Solusi terbaik adalah mengubah API Anda sehingga API menggunakan kode status 204 yang benar secara semantik saat badan kosong, atau mengembalikan sesuatu di 200 badan respons. Saya pikir bahkan objek yang dikodekan JSON kosong akan berfungsi, selama hanya ada sesuatu di badan respons yang merupakan JSON yang valid.

Jika Anda benar-benar tidak dapat mengubah API, mungkin Anda dapat meneruskan fungsi kustom fetch menjadi apollo-link-rest seandainya Anda dapat memeriksa dan mengubah respons sebelum akhirnya kembali untuk memproses ALR. Ini akan menjadi peretasan, tetapi mungkin berhasil untuk Anda.

Atau, sekali lagi, pastikan API mengembalikan header Content-length: 0 dalam responsnya.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat