成功すると204の「コンテンツなし」ステータスで応答するミューテーションリクエストがあります。 apollo-link-errorと組み合わせると、常にネットワークエラーが発生します: 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_ですが、応答フィールドがないとミューテーションを送信できません...何かが足りない場合を除きます。
@ 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は私の最後のコメントを気にしません。 ブラウザの実装は、テスト環境よりも寛容ではないようです。
空のボディを検出する際に私が目にする問題の1つは、 res.json()
またはres.text()
を呼び出さずにボディに何があるかを判断する確実な方法がなく、万が一の場合に備えて常に両方を呼び出すことです。冗長。 そうでなければ、 Content-Length
ヘッダーを見るかもしれませんが、それが常に信頼できるかどうかはわかりません。 別のオプションは、 Content-Type
がapplication/json
場合にのみJSONを解析することですが、一部のAPIは、すべての応答に共通のヘッダーを設定し、空の204応答にも設定する可能性があります。
残りのリンクは300を超えるステータスコードでnetworkError
を生成するため、応答解析は2xxステータスコードを正しく処理するために十分に特殊化する必要があります。 遭遇することが合理的に予想されるもののうち、次のとおりです。
204の応答は、空の本文を持つ唯一の応答である必要があります。 ステータスコードを調べて、204のときにデフォルトの{}
を返すオプションはありますか? これは非常に特殊なエッジケースのテストですが、ライブラリをよりHTTP標準に準拠させるため、良いことのように思われます。
@fbarthoこれらのアプローチのいずれかを好みますか? これらのオプションの1つ、またはそれらの組み合わせが妥当と思われる場合は、PRを作成します。
おそらくここに中道がありますか? 両方の動作をサポートできますか?
私は204をデフォルトで{}として解釈することをかなり支持していますか、それとも「null」はnullであり、JSONにコンテンツがないことと意味的に同等ですか?
空のボディのアップストリームGraphQL解釈が機能するためには、 {}
を返す必要があると思います。
data: {
__typename: "...",
NoResponse: null,
}
「両方の動作をサポートできますか?」と言うとき 204ステータスコードとヘッダーを確認するという意味ですか? Content-Length
が実際に存在し、 0
も存在する場合、それを空の本体の別の指標と見なして、デフォルトを返すことができると思います。
以前にContent-Type
ヘッダーを提案しましたが、実際には、 json
以外に設定されたときに何をすべきかが明確ではありません。 このヘッダーを解釈する場合は、提案されているbodySerializer
と同様のresponseSerializer
オプションを使用して実行する必要があると思います。 それはおそらくやり過ぎであり、特に空の体の問題には対処しません。
204とContent-Lengthの実装ができてうれしいです。
これまでのところ、私は以前のアドバイスに従い、204応答を処理するためにカスタムフェッチを実装しました。 しかし、私は適切な応答を取り戻すのに苦労しました。 この機能をすぐに使用できるオプションがあると便利です。
残念ながら、私はまだJSの世界をナビゲートする方法を学んでいます...
#111で修正!
甘い! どうもありがとうございました。
さて、まだ残っている小さな問題は1つだけです:)自分の一時的な解決策を考え出した直後に、ターゲットSharePointServerのRESTAPIでさらに別の問題が発生しました...エントリを削除すると、200の応答が返されますボディコンテンツなし:)
動作を一般化できる可能性がありますか。つまり、本文のコンテンツが「NoResponse」タグで応答しない場合はどうでしょうか。 私が間違っていない場合、パッチは現在、204の特殊なケースのみに対応しています。
@isopterixサーバーがContent-Length
を適切にゼロに設定した場合、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.text()
の代わりにres.json()
して解析する前に、有効なJSONをチェックJSON.parse()
。 これは、ストリーミングJSON解析を緩めることを意味し、そのため、実行される可能性は低いです。
最善の解決策は、本文が空のときに意味的に正しいステータスコード204を使用するようにAPIを変更するか、200応答本文で何かを返すことです。 応答本文に有効なJSONであるものがあれば、空のJSONエンコードオブジェクトでも機能すると思います。
APIを本当に変更できない場合は、カスタムのfetch
関数をapollo-link-rest
渡して、最終的にALRに戻って処理する前に、応答を調べて変更することができます。 それはハックになるでしょうが、それはあなたのために働くかもしれません。
または、APIが応答でContent-length: 0
ヘッダーを返すことを確認してください。
最も参考になるコメント
空のボディのアップストリームGraphQL解釈が機能するためには、
{}
を返す必要があると思います。「両方の動作をサポートできますか?」と言うとき 204ステータスコードとヘッダーを確認するという意味ですか?
Content-Length
が実際に存在し、0
も存在する場合、それを空の本体の別の指標と見なして、デフォルトを返すことができると思います。以前に
Content-Type
ヘッダーを提案しましたが、実際には、json
以外に設定されたときに何をすべきかが明確ではありません。 このヘッダーを解釈する場合は、提案されているbodySerializer
と同様のresponseSerializer
オプションを使用して実行する必要があると思います。 それはおそらくやり過ぎであり、特に空の体の問題には対処しません。204とContent-Lengthの実装ができてうれしいです。