I have a simple Flask API:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/add/<params>', methods = ['GET'])
def add_numbers(params):
#params is expected to be a dictionary: {'x': 1, 'y':2}
params = eval(params)
return jsonify({'sum': params['x'] + params['y']})
if __name__ == '__main__':
app.run(debug=True)
Now, I want to call this method from Java and extract the result. I have tried using java.net.URL and java.net.HttpURLConnection;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class MyClass {
public static void main(String[] args) {
try {
URL url = new URL("http://127.0.0.1:5000/add/{'x':100, 'y':1}");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
}
But it doesn't work. In the flask server I get an error message:
code 400, message Bad request syntax ("GET /add/{'x':100, 'y':1} HTTP/1.1")
"GET /add/{'x':100, 'y':1} HTTP/1.1" HTTPStatus.BAD_REQUEST -
and in Java code, I get the error:
Exception in thread "main" java.lang.RuntimeException: Failed : HTTP error code : -1 at MyClass.main(MyClass.java:17)
What am I doing wrong?
My final aim is to pass dictionary objects to my python function and return the response of the function to java. The dictionary can contain text values of over thousand words. How can I achieve this?
Edit
Based on the comments and the answers, I have updated my Flask code to avoid using eval and for better design:
@app.route('/add/', methods = ['GET'])
def add_numbers():
params = {'x': int(request.args['x']), 'y': int(request.args['y']), 'text': request.args['text']}
print(params['text'])
return jsonify({'sum': params['x'] + params['y']})
Now my Url is: "http://127.0.0.1:5000/add?x=100&y=12&text='Test'"
Is this better?
As from @TallChuck's comment above, you need to replace or remove spaces in the URL
URL url = new URL("http://127.0.0.1:5000/add?x=100&y=12&text='Test'");
I would suggest to make use of a request object to retrieve parameters in your GET call.
The Request Object
To access the incoming data in Flask, you have to use the request object. The request object holds all incoming data from the request, which includes the mimetype, referrer, IP address, raw data, HTTP method, and headers, among other things. Although all the information the request object holds can be useful we'll only focus on the data that is normally directly supplied by the caller of our endpoint.
As mentioned in the comments to post large amounts of paramters and data, A more appropriate implementation for this task would be probably using the POST method.
Here's an example about the same implementation for POST in the backend:
from flask import Flask, jsonify, request
import json
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/add/', methods = ['POST'])
def add_numbers():
if request.method == 'POST':
decoded_data = request.data.decode('utf-8')
params = json.loads(decoded_data)
return jsonify({'sum': params['x'] + params['y']})
if __name__ == '__main__':
app.run(debug=True)
Here's a simple way to test the POST backend using cURL:
curl -d '{"x":5, "y":10}' -H "Content-Type: application/json" -X POST http://localhost:5000/add
Using Java to post the request:
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class PostClass {
public static void main(String args[]){
HttpURLConnection conn = null;
DataOutputStream os = null;
try{
URL url = new URL("http://127.0.0.1:5000/add/"); //important to add the trailing slash after add
String[] inputData = {"{\"x\": 5, \"y\": 8, \"text\":\"random text\"}",
"{\"x\":5, \"y\":14, \"text\":\"testing\"}"};
for(String input: inputData){
byte[] postData = input.getBytes(StandardCharsets.UTF_8);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty( "charset", "utf-8");
conn.setRequestProperty("Content-Length", Integer.toString(input.length()));
os = new DataOutputStream(conn.getOutputStream());
os.write(postData);
os.flush();
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}finally
{
if(conn != null)
{
conn.disconnect();
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With