ここでの問題は、オースティン・フィリップスが指摘したように、urllib2.Request
のコンストラクタのdata
パラメータ、ということである:
をサーバーに送信するために追加のデータを指定する文字列かもしれ... data
は標準でバッファする必要がありますアプリケーション/ x-www-form-urlencodedフォーマット。 urllib.urlencode()関数は2タプルのマッピングまたはシーケンスを取り、この形式の文字列を返します。
URLエンコードされたデータの代わりに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リクエストを送信し、端末にダンプされます。それをコピーしてnc HOST 80
を使用して貼り付けて、実際のサーバーがどのように応答するかを確認し、それを使って問題がどこにあるかを絞り込むことができます。または、あなたが立ち往生した場合は、少なくともコピーしてあなたのSOの質問にデータを貼り付けることができます。
最後に一つは:(あなたがrequests
とまったく同じデータを送っているし、それが働いているので)これはほぼ確実にあなたの問題には関係ありませんが、それは、単一の使用しているので、あなたのデータは、実際に有効なJSONではありません二重引用符の代わりに引用符。 the docsによると、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では有効でないバックスラッシュエスケープや、解析に制限付き評価(または悪い評価)を使用するJSコードなども認められます。また、多くの人が悪いJSONを書くことに慣れているので、多くのブラウザのネイティブなJSONパーサと他の言語のJSONライブラリの多くは、一般的なエラーを回避するための回避策があります。しかし、あなたはそれに頼るべきではありません。
2者が送信したヘッダーを比較すると、両者は同じではありません。 (例えば、 'requests'はデフォルトで' Accept-Encoding:gzip、deflate、compress'を行い、 'urllib'を' Accept-Encoding:identity'にします。)リクエストヘッダを各バージョンで取得し、例えば、 'nc'とそれがどのように応答するか見ることができます。'urllib2'ヘッダに関する何かが502エラーを引き起こしているか、何らかのリダイレクト/ etcをしています。その要求はurllib2によって理解することはできません。 – abarnert
また、 'requests'で動作する場合、単に' requests'を使うことができない理由がありますか? – abarnert
['urllib2.Request'](http://docs.python.org/2/library/urllib2.html#urllib2.Request)のドキュメントによれば、* data *パラメータは* application/x- www-form-urlencoded * –