각각의 언어에서 form데이터를 보내야 할 때가 있다.
필자가 이걸 사용하면서 꽤 고생했던 적이 있어서 이번에 한번 언급하려고 한다.
사실 알고나면 매우 쉬운데 잘못 알려져 있는데가 꽤 많았다.
그래서 RESTful을 만들때 참고해라고 만들어 둔다.
from flask import Flask, request
import json
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def hello_world():
data = {}
if request.method == 'POST':
data = request.json
print(data)
data['name'] = data['name'] + 'hi'
data['age'] = data['age'] + 100
return json.dumps(data)
if __name__ == '__main__':
app.run()
일단 테스트용 서버는 위와 같다. 위는 파이썬 플라스크로 만들어져 있다.
파이썬 플라스크의 정보는 필자 블로그에도 연재를 하고 있다.
현재 시간 2018년 10월 기준으로는 연재중단중이지만 언제 연재를 시작할지는 잘 모르나 일단 링크를 걸어둔다.
위의 서버는 매우 간단하다.
POST에서 데이터를 받는데 이를 request.json으로 받는다.
즉 대놓고 json으로 받겠다는 선언이다.
만약 형식이 json이 아니다? 그러면 그냥 에러코드 500을 날려줄것이다. 실패하기 때문이다.
그래서 우리는 form데이터를 보낼 때, 이를 json형태로 파싱해서 보내줘야한다는 것이다.
그리고 다시 돌려보내줄것인데 이 때 돌려받았다는걸 확인하기 위해서 값을 약간 변조할 것이다.
사실 안해줘도 되지만...
//https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.5
package com.company;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class Main2 {
public static void main(String[] args) {
String strUrl = "http://localhost:5000";
String strMethod = "post";
BufferedReader in = null;
try {
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse("{'name':'kukaro','age':26}");
URL url = new URL(strUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.setRequestMethod(strMethod.toUpperCase());
PrintStream ps = new PrintStream(con.getOutputStream());
ps.print(jsonObject);
ps.close();
con.disconnect();
in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
jsonObject = (JsonObject) jsonParser.parse(in);
System.out.println(jsonObject);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
뭔가 코드가 굉장히 길어졌다.
사실 보면 뭐 별건 없다.
con.setDoOutput(true);
출력 모드를 true로 해줘야 output을 쓸 수가 있다.
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
헤더를 application/json으로 바꿔준다.
이렇게 보내야 데이터가 json으로 오고감을 알려줄 수 있다.
PrintStream ps = new PrintStream(con.getOutputStream());
ps.print(jsonObject);
ps.close();
PrintStream을 선언해주고 거기에 우리가 만든 jsonObject를 넣어주면된다.
const request = require('request');
request({
url: 'http://localhost:5000',
method: 'post',
headers: {'Content-Type': 'application/json'},
json: true,
body: {
'name': 'kukaro',
'age': 26
}
}, (err, res, body) => {
console.log(body);
});
여기서는 비슷한데 headers를 application/json으로 선언하면 반환값이 json이 되므로 body가 json그 자체가된다.
만약 헤더를 설정하지 않는다면 반환값은 json이 아니라 json을 문자열로 직렬화 시킨 값이 도착한다.
반드시 json true를 해줘야 값이 전달된다.
import requests
form = {
'name': 'kukaro',
'age': 26
}
data = requests.post('http://localhost:5000/', json=form)
print(data.json())
특별할것도 없지만 매우 짧다. 데이터를 json으로 해서 넣어준다는 특별한 점이 있다.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
strURI := "http://localhost:5000"
jsonBody := map[string]interface{}{}
jsonBody["name"] = "kukaro"
jsonBody["age"] = 26
jsonStr, _ := json.Marshal(jsonBody)
resp, _ := http.Post(strURI, "application/json; charset=UTF-8", bytes.NewBuffer([]byte(jsonStr)))
respBody, _ := ioutil.ReadAll(resp.Body)
jsonData := map[string]interface{}{}
json.Unmarshal(respBody, &jsonData)
fmt.Println(jsonData)
}
여기서도 마찬가지로 컨텐트 타입을 추가해준다. 그리고 json데이터를 직렬화해서 값을 http.Post의 세번째 인자로 넣어준다.