简体   繁体   中英

How can I successfully post JSON via C# to a Python Flask route that authenticates via the JSON content?

I've written a rudimentary API in a Flask project to allow POSTing data via JSON strings. The JSON requires two properties: username and apikey , which are validated through the following decorator:

def apikey_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not request.json:
            abort(404)
        json_data = request.json
        if not 'username' in json_data or not 'apikey' in json_data:
            abort(404)
        user = User.query.filter(User.username == json_data['username']).first()
        if not user or user.status != "superuser":
            abort(404)
        if not user.apikey or user.apikey != json_data['apikey']:
            return jsonify({'status': 'error', 'message': 'unrecognized API key'})
        return f(*args, **kwargs)
    return decorated_function

I've written routes utilizing this decorator and they work beautifully in Python applications: Here's the basic structure of an API route:

@mod.route('/invadd', methods=['GET', 'POST'])
@apikey_required
def invadd():
    json = request.json
#lots of application-specific logic that passes unit tests

My Flask unit tests work fine:

good_post_response = self.app.post(
   'api/invadd', data=json.dumps(test_json), 
   content_type='application/json') # assertions which verify the reponse pass

Python applications I've written work fine:

response = urllib2.urlopen(req, json.dumps(post_json)) #req is an api route URL
response_json = json.loads(response.read())

But in my C# app, I get a SocketException: No connection could be made because the target machine actively refused it. when I try to post JSON to these same routes. Here's a relevant code snippet:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create();
request.ContentType = "application/json";
request.Method = "POST";
request.ContentLength = postJSON.Length;
using (StreamWriter sw = new StreamWriter(request.GetRequestStream()))  <--- FAILURE POINT
{
    sw.Write(postJSON.ToString());
    sw.Flush();
    sw.Close();
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
    string result = sr.ReadToEnd();
    AddFeedback(result);
}

I've also tried using the WebClient class:

 WebClient wc = new WebClient();
 AddFeedback(String.Format("Processing order {0}", order.OrderID));
 string postJSON = BuildJSON(order);
 string url = String.Format("{0}api/invadd", gslBase); //I verified that the URL is correctly constructed
 string response = wc.UploadString(url, "POST", postJSON);
 AddFeedback(response);

It's clear to me that the failure happens when the app tries to initiate the connection to the route, as it never gets to the point where it's actually trying to post the JSON data. But I'm not sure how to get around this. Do I need to change my Flask route?

That kind of exception indicates that there was a error at the socket level - that's before you reach JSON, or even HTTP.

Make sure you're connecting to the right machine and the right port.

It's not clear where you're inputting that data on your C# code - you probably should be using WebRequest.Create("yoururl") .

You can also try to connect using a browser, and see if it works.

If all those details are right, you can use wireshark to check what, exactly, is causing the connection to fail

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM