6

Python(WSGI)とNodeJS+Expressアプリケーションの間でPOSTリクエストを作成しようとしています。それらは異なるサーバー上にあります。

問題は、異なるIPアドレス(つまり、プライベートネットワークとパブリックネットワーク)を使用すると、パブリックネットワークでの要求は成功しますが、プライベートネットワークに対する同じ要求はまたは urllib2で失敗することです。502 Bad GatewayURLError [32] Broken pipe

urllib2私が使用しているコードは次のとおりです。

req = urllib2.Request(url, "{'some':'data'}", {'Content-Type' : 'application/json; charset=utf-8'})

res = urllib2.urlopen(req)

print f.read()

今、私もこのようにリクエストをコーディングしましたrequests

r = requests.post(url, headers = {'Content-Type' : 'application/json; charset=utf-8'}, data = "{'some':'data'}")

print r.text

そして、200 OK応答を取得します。この代替方法は、両方のネットワークで機能します。

知らないリクエストに必要な追加の構成があるかどうか、または欠落している可能性のあるネットワーク構成を調べる必要があるかどうかを調べることに興味がありurllib2ます(これが当てはまるとは思わないので、別のリクエスト方法は機能しますが、間違いなく間違っている可能性があります)。

これに関する提案やポインタは大歓迎です。ありがとう!

4

1 に答える 1

3

ここでの問題は、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ライブラリには、一般的なエラーを許可する回避策があります。しかし、それに頼るべきではありません。

于 2013-02-05T19:30:35.237 に答える