ここでの問題は、Austin Phillipsが指摘したように、urllib2.Request
のコンストラクターのdata
パラメーターは次のとおりです。
サーバーに送信する追加データを指定する文字列である可能性があります…data
標準のapplication/x-www-form-urlencoded形式のバッファーである必要があります。urllib.urlencode()関数は、2タプルのマッピングまたはシーケンスを取り、この形式の文字列を返します。
urlencodedデータの代わりにJSONエンコードされたデータを渡すことで、どこかで混乱します。
ただし、Request
メソッドがありますadd_data
:
リクエストデータをデータに設定します。これは、HTTPハンドラーを除くすべてのハンドラーによって無視されます。バイト文字列が必要であり、要求がGETではなくPOSTに変更されます。
これを使用する場合add_header
は、コンストラクターに渡すのではなく、おそらく使用する必要がありますが、ドキュメントのどこにも具体的に言及されていないようです。
したがって、これは機能するはずです。
req = urllib2.Request(url)
req.add_data("{'some':'data'}")
req.add_header('Content-Type', 'application/json; charset=utf-8')
res = urllib2.urlopen(req)
コメントで、あなたは言った:
この問題が発生している理由を特定せずにリクエストに切り替えたくない理由は、これが指摘するより深い根本的な問題が戻ってきて、後で検出が困難になる可能性があるためです。 。
根底にある深い問題を見つけたい場合は、クライアント側のソースを調べるだけではそれを行うことはできません。「Xは機能するのにYは失敗するのはなぜですか?」を理解するための最初のステップ ネットワークコードを使用すると、XとYがそれぞれ送信するバイトを正確に把握できます。次に、関連する違いを絞り込み、コードのどの部分がYに関連する場所で間違ったデータを送信させているのかを突き止めます。
これは、サービスでログを記録したり(制御している場合)、Wiresharkを実行したりすることで実行できますが、単純な場合の最も簡単な方法はnetcatです。man nc
構文はバージョンごとに異なるため、システムを読み取る必要があります(また、Windowsでは、実行する前にnetcatを取得してインストールする必要があります)が、常にのような単純なものnc -kl 12345
です。
次に、クライアントでlocalhost:12345
、ホスト名の代わりに使用するURLを変更すると、netcatに接続し、HTTPリクエストを送信します。HTTPリクエストはターミナルにダンプされます。次に、それをコピーして使用nc HOST 80
および貼り付けて、実サーバーがどのように応答するかを確認し、それを使用して問題のある場所を絞り込むことができます。または、行き詰まった場合は、少なくともデータをコピーしてSOの質問に貼り付けることができます。
最後にもう1つ:これは問題とはほとんど関係ありませんが(まったく同じデータを送信していて機能しているためrequests
)、データは二重引用符ではなく一重引用符を使用しているため、実際には有効なJSONではありません。ドキュメントによると、string
は次のように定義されています。
string
""
" chars "
(ドキュメントにも優れたグラフィック表現があります。)
一般に、非常に単純なテストケースを除いて、JSONを手動で記述したくはありません。多くの場合(あなたを含む)、あなたがしなければならないのは、"…"
をjson.dumps(…)
に置き換えることだけなので、これは深刻な困難ではありません。それで:
req = urllib2.Request(url)
req.add_data(json.dumps({'some':'data'}))
req.add_header('Content-Type', 'application/json; charset=utf-8')
res = urllib2.urlopen(req)
それで、なぜそれが機能しているのですか?そうですね、JavaScriptでは、一重引用符で囲まれた文字列は合法であり、JSONでは無効なバックスラッシュエスケープなどの他のものもあります。解析にrestricted-eval(またはさらに悪いことにraw eval)を使用するJSコードはそれを受け入れます。 。また、多くの人がこのために悪いJSONを書くことに慣れているため、多くのブラウザーのネイティブJSONパーサーと他の言語の多くのJSONライブラリには、一般的なエラーを許可する回避策があります。しかし、それに頼るべきではありません。