Apollo-link-rest: خطأ عندما تكون استجابة REST فارغة

تم إنشاؤها على ٧ مايو ٢٠١٨  ·  18تعليقات  ·  مصدر: apollographql/apollo-link-rest


لدي طلب طفرة والذي عند نجاحه يستجيب بحالة 204 "بلا محتوى". عندما يقترن بخطأ apollo-link ، أتلقى باستمرار خطأ في الشبكة: نهاية غير متوقعة لإدخال JSON .

يبدو أن Apollo-link-rest تحاول تحليل الجسم الفارغ للاستجابة.

أي أفكار حول كيفية التخفيف من هذا؟ راجع للشغل أحاول التحدث إلى 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 . أعتقد أنه إذا كان سيتم تفسير هذا العنوان ، فربما يلزم تنفيذه باستخدام خيار تكوين responseSerializer مشابه للخيار bodySerializer المقترح. ربما يكون هذا مبالغة ، ولن يعالج مشكلة الجسم الفارغ على وجه الخصوص.

يسعدني تنفيذ 204 وطول المحتوى.

ال 18 كومينتر

isopterix - لا أعتقد أن لدينا حقًا طريقة سهلة للتعامل مع هذا في الوقت الحالي. - فكرتي المبدئية هي أن أوصيك بلف الجلب وتقديم تنفيذ إحضار مخصص يستبدل نص 204 إجابة بـ {} - أعتقد أنه بدون إنشاء ميزة أفضل ، هذه هي الطريقة الوحيدة التي يمكنني من خلالها القيام بذلك اليوم!

isopterix لقد حاولت إعادة إنتاج هذه المشكلة من خلال الاختبار أدناه ، لكن الاختبار يمر لجسم فارغ. يبدو أن جلب 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 ، لكنني لست متأكدًا مما إذا كان سيكون دائمًا موثوقًا به. قد يكون الخيار الآخر هو تحليل JSON فقط إذا كان Content-Type هو application/json ، ولكن من الممكن أيضًا أن تقوم بعض واجهات برمجة التطبيقات بتعيين هذا العنوان بشكل مشترك لجميع الردود وحتى على استجابة 204 فارغة.

نظرًا لأن ارتباط الباقي ينتج networkError على أي رمز حالة أعلى من 300 ، فإن تحليل الاستجابة يحتاج فقط إلى التخصص الكافي للتعامل مع رموز الحالة 2xx بشكل صحيح. من بين الأشخاص الذين قد يتوقع المرء بشكل معقول أن يواجهوه ، كونهم:

  • 200 جيد
  • 201 تم الإنشاء
  • 202 مقبولة
  • 204 لا يوجد محتوى
  • (أي من الآخرين؟)

يجب أن تكون الردود 204 هي الوحيدة التي تحتوي على جسم فارغ. هل سيكون خيارًا لفحص رمز الحالة وإرجاع {} الافتراضي عندما يكون 204؟ في حين أنه سيكون اختبارًا لحالة حافة محددة جدًا ، إلا أنه سيجعل المكتبة أكثر توافقًا مع معيار HTTP والذي يبدو أنه أمر جيد.

fbartho هل لديك أي تفضيل لأحد هذه الأساليب؟ سأجعل العلاقات العامة إذا كان أحد هذه الخيارات ، أو مجموعة منها ، يبدو معقولاً.

ربما هناك طريق وسط هنا؟ هل يمكن دعم كلا السلوكين؟

أنا أؤيد بشدة تفسير 204 على أنها {} افتراضيًا بنفسي ، أو أن كلمة "خالية" لاغية هي المكافئ الدلالي لعدم وجود محتوى في JSON؟

أعتقد أنه لكي يعمل تفسير GraphQL الأولي للجسم الفارغ ، يجب أن نعيد {} والذي سينتج عنه بعد ذلك

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

عندما تقول "هل يمكن دعم كلا السلوكين؟" هل تقصد النظر إلى رمز الحالة 204 والنظر إلى الرؤوس؟ أعتقد أنه عندما يكون Content-Length موجودًا بالفعل وأيضًا 0 يمكننا اعتبار ذلك مؤشرًا آخر على وجود جسم فارغ وإرجاع القيمة الافتراضية.

على الرغم من أنني اقترحت رأس Content-Type سابقًا ، فأنا في الواقع لست واضحًا تمامًا بشأن ما يجب القيام به عند تعيينه على شيء آخر غير json . أعتقد أنه إذا كان سيتم تفسير هذا العنوان ، فربما يلزم تنفيذه باستخدام خيار تكوين responseSerializer مشابه للخيار bodySerializer المقترح. ربما يكون هذا مبالغة ، ولن يعالج مشكلة الجسم الفارغ على وجه الخصوص.

يسعدني تنفيذ 204 وطول المحتوى.

حتى الآن اتبعت النصيحة السابقة ونفذت عملية إحضار مخصصة للتعامل مع استجابة 204. لكني واجهت صعوبة في الحصول على رد مناسب. سيكون الحصول على خيار إخراج هذه الوظيفة من الصندوق أمرًا رائعًا.

لسوء الحظ ، ما زلت أتعلم كيفية التنقل في عالم JS ...

تم الإصلاح عبر # 111!

حلو! شكرا جزيلا.

الآن ، لا تزال هناك مشكلة صغيرة واحدة متبقية :) مباشرة بعد أن توصلت إلى حل مؤقت خاص بي ، واجهت مشكلة أخرى مع واجهة برمجة تطبيقات REST لخادم SharePoint المستهدف ... إذا قمت بحذف إدخال ، فستحصل على استجابة 200 مع عدم وجود محتوى الجسم :)

هل يمكننا تعميم السلوك ، أي إذا لم يكن هناك محتوى جسدي يستجيب بعلامة "NoResponse"؟ إذا لم أكن مخطئًا ، فإن التصحيح حاليًا يعالج فقط الحالة الخاصة 204.

isopterix إذا قام الخادم بتعيين Content-Length إلى الصفر بشكل صحيح ، يجب أن يعمل حتى مع 200 استجابة ، والقصد هو التحقق من ذلك أيضًا.

نتطلع إلى إعطائها تدور.

هل يغطي هذا أي استجابة ناجحة بمحتوى فارغ؟ مثل 200 مع عدم وجود محتوى؟

نعم. الإصلاح الذي تم دمجه لهذا الشيكات لحالة 204 أو رأس Content-Length: 0 وإرجاع كائن فارغ.

إذا كان لديك 200 إجابة فارغة بدون رأس Content-Length فلن تعمل لأن النص لم يتم تحليله لهذا الفحص.

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.text() بدلاً من res.json() والتحقق من JSON صالح قبل التحليل باستخدام JSON.parse() . هذا يعني أنك تفقد عملية تحليل JSON المتدفقة وبالتالي ليس من المحتمل القيام بشيء ما.

أفضل حل هو تغيير واجهة برمجة التطبيقات (API) الخاصة بك بحيث تستخدم رمز الحالة الصحيح المعنوي 204 عندما يكون النص فارغًا ، أو إرجاع شيء ما في نص استجابة 200. أعتقد أنه حتى الكائن المشفر JSON الفارغ سيعمل ، طالما هناك شيء ما في نص الاستجابة صالح JSON.

إذا كنت لا تستطيع تغيير واجهة برمجة التطبيقات ، فربما يمكنك تمرير دالة مخصصة fetch إلى apollo-link-rest حيث يمكنك فحص الاستجابة وتغييرها قبل العودة في النهاية إلى ALR للمعالجة. سيكون اختراقًا ، لكنه قد يعمل من أجلك.

أو ، مرة أخرى ، تأكد فقط من أن واجهة برمجة التطبيقات تُرجع رأس Content-length: 0 في الاستجابة.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات