Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- db
- 자바
- 데이터베이스
- 스프링
- mybatis
- 이클립스
- mysql
- TIL
- 알고리즘
- 플라스크
- javascript
- jQuery
- sql
- 백준
- BOJ
- spring
- 링크
- eclipse
- java
- database
- 오라클
- Git
- 파이썬
- 웹프로그래밍
- 자바스크립트
- rdbms
- flask
- Oracle
- PYTHON
- 에러
Archives
- Today
- Total
기록과 정리의 공간
[Flask] Flask로 REST API 구현하기 / CORS란? 본문
Flask로 REST API를 구현하는 방법
URI요청에 대한 응답을 JSON형식으로 작성하여 데이터를 반환하도록 만들면 된다.
Flask에서는 딕셔너리 형태로 데이터를 만들고, 이를 jsonify() 메서드를 활용해 JSON포맷의 데이터로 만들 수 있다.
각 요청 메서드마다 파라미터값을 추출하는 방식이 다르다.
- GET/PUT/DELETE는 방식이 동일, POST만 다르다.
- GET/PUT/DELETE는 request.args.get('파라미터이름') 으로 가져온다. (파라미터가 가진 값을 가져옴)
- POST는 request.get_json() 으로 데이터를 가져온다. 이 때, 딕셔너리 형태로 가져오는데, 원하는 파라미터가 가지고 있는 값에 접근하려면 key로 접근하면 된다.(ex> data = request.get_json()으로 가져온다고 하면, 'email'이라는 파라미터의 값에 접근하고자할 때, data['email'])
- GET/PUT/DELETE는 방식이 동일, POST만 다르다.
API리턴값은 flask의 jsonify()함수를 사용하여 JSON포맷으로 보내줘야 한다.
HTTPie 툴을 활용하자.(상단의 두 번째 참고 링크의 #5번 참고)
예시 코드 - 프론트엔드(vue.js)와 flask를 이용하여 REST API를 구현한 코드
결과값은 코드를 실행하여 직접 확인해보자.
flask 코드
- #1, #2는 아래쪽의 CORS란? 참고
- #3 : flask의 make_response() 는 아래 #1 라인에서 상태 코드를 함께 넘겨준 것 처럼, 응답을 좀 더 명시적으로 리턴하기 위해 사용한다.(공식 문서) 이는 HTTPie 로 응답 헤더를 직접 확인해보면 알 수 있다.
html 코드
vue로 제어할 코드는 id가 app인 div태그로 감싸져 있는 부분이다.
button 태그 : vue template에서 각 버튼 클릭시, 각 버튼에 연결된 함수를 호출하는 코드
restapi_test.html 코드에서 아래의 세 번째 script 태그 안의 코드
- 프론트엔드(vue.js)에서 axios를 이용해 HTTP를 요청하는 코드이다.(백엔드 쪽으로 요청 메서드 및 파라미터값을 전달한다.)
- HTTP요청 메서드는 method: 에 넣어주면 된다.
- GET, PUT, DELETE 는 params:에 데이터를 JSON형식으로 넣어주면 된다.
- POST는 data:에 JSON형식으로 넣으면 된다.
- 프론트엔드(vue.js)에서 axios를 이용해 HTTP를 요청하는 코드이다.(백엔드 쪽으로 요청 메서드 및 파라미터값을 전달한다.)
flask코드에서 jsonify()함수를 사용해, JSON형식으로 리턴된 값은 response.data에 담겨져있다. 해당 데이터를 JSON데이터를 꺼내듯이 추출하면 된다.
# flask 코드
from flask import Flask, request, make_response, jsonify, render_template
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/test", methods=['GET', 'POST', 'PUT', 'DELETE'])
def test():
if request.method == 'POST':
print('POST')
data = request.get_json()
print(data)
print(data['email'])
if request.method == 'GET':
print('GET')
user = request.args.get('email')
print(user)
if request.method == 'PUT':
print('PUT')
user = request.args.get('email')
print(user)
if request.method == 'DELETE':
print('DELETE')
user = request.args.get('email')
print(user)
return make_response(jsonify({'status': True}), 200)
@app.route("/html_test")
def html_test():
return render_template('vue_restapi_test.html')
if __name__ == '__main__':
app.run(host="0.0.0.0", port="8082")
<!-- restapi_test.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<!-- Bootstrap CSS -->
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
crossorigin="anonymous"
/>
<title>Hello, world!</title>
</head>
<body>
<div id="app">
<br />
<center>
<button type="button" class="btn btn-primary" v-on:click="test_get">
GET
</button>
<button type="button" class="btn btn-secondary" v-on:click="test_post">
POST
</button>
<button type="button" class="btn btn-success" v-on:click="test_put">
PUT
</button>
<button type="button" class="btn btn-danger" v-on:click="test_delete">
DELETE
</button>
</center>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script
src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"
></script>
<script
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"
></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"
integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI"
crossorigin="anonymous"
></script>
<!-- Vue Start -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const app = new Vue({
el: "#app",
methods: {
test_get: () => {
axios("http://localhost:8082/test", {
method: "get",
params: {
email: "test@test.com",
},
})
.then((response) => {
console.log(response.data["status"]);
})
.catch((error) => {
console.log(error);
});
},
test_post: () => {
axios("http://localhost:8082/test", {
method: "post",
data: {
email: "test@test.com",
},
})
.then((response) => {
console.log(response.data["status"]);
})
.catch((error) => {
console.log(error);
});
},
test_put: () => {
axios("http://localhost:8082/test", {
method: "put",
params: {
email: "test@test.com",
},
})
.then((response) => {
console.log(response.data["status"]);
})
.catch((error) => {
console.log(error);
});
},
test_delete: () => {
axios("http://localhost:8082/test", {
method: "delete",
params: {
email: "test@test.com",
},
})
.then((response) => {
console.log(response.data["status"]);
})
.catch((error) => {
console.log(error);
});
},
},
});
</script>
</body>
</html>
CORS(Cross Origin Resource Sharing, 교차 출처 리소스 공유)란?
웹 페이지 상의 제한된 리소스를 최초 자원이 서비스된 도메인 밖의 다른 도메인으로부터 요청할 수 있게 허용하는 구조이다. (위키백과)
등장하게 된 배경
- 웹에서 사용하는 HTTP request는 기본적으로 다른 도메인의 데이터를 요청할 수 있다.
- 예를 들어, 내가 접속한 웹페이지가 www.test.com/index.html 라고 하면, 해당 웹페이지 안에서 html태그로 www.image.com/image1.jpg 파일을 가져와서 이미지로 보여줄 수 있다. 그러나, script태그로 둘러싸인 코드에서 실행되는 HTTP request는 동일한 출처(www.test.com) 에만 요청할 수 있다. 이를 Same Origin Policy라고 한다. 정확하게는 프로토콜, 호스트명, 포트가 동일해야 한다.
- 만약 다른 서버에 HTTP request를 요청한다면, 아래와 같은 에러가 뜬다.
- HTTP 응답 헤더에 Access-Contorl-Allow-Origin 관련 정보가 없기 때문에 CORS를 허용하지 않는다는 의미이다.
- Same Origin Policy(동일 출처 정책) : 웹 브라우저의 기본 정책으로, 어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 중요한 보안 방식이다. 동일 출처 정책은 잠재적으로 해로울 수 있는 문서를 분리함으로써 공격받을 수 있는 경로를 줄여준다. (링크)
- ajax, axios와 같은 기술이 생김에 따라, 다른 서버로의 데이터 요청을 지원해야한다는 요구가 생겨 CORS라는 가이드가 마련되었다고 한다. (각 언어별로)
- 웹에서 사용하는 HTTP request는 기본적으로 다른 도메인의 데이터를 요청할 수 있다.
(링크)에 따르면, CORS는 다음과 같은 방법으로 허용할 수 있다고 한다.
- 프론트엔드에서는 요청 헤더에 CORS관련 옵션을 추가하고,
- 서버에서는 응답 헤더에 CORS관련 옵션을 추가해줘야 한다.
flask 서비스에 CORS 지원하는 방법
- flask_cors 라이브러리 install (공식 문서)
pip install flask_cors
- 사용법
- 아래 코드와 같이 CORS(Flask객체) 를 선언해주면, 전체 요청/응답 헤더에 CORS 지원 헤더 정보를 넣어서 CORS를 지원해준다.
- HTTP 응답헤더를 확인해보면 헤더에 Access-Control-Allow-Origin 부분이 추가되고, 요청한 데이터를 다른 서버에서 정상적으로 가져오게 된다.
- 아래 코드와 같이 CORS(Flask객체) 를 선언해주면, 전체 요청/응답 헤더에 CORS 지원 헤더 정보를 넣어서 CORS를 지원해준다.
from flask_cors import CORS
app = Flask(name)
CORS(app)
'라이브러리&프레임워크 > Flask' 카테고리의 다른 글
[Flask] 메시지 플래싱(Message Flashing) (0) | 2020.08.07 |
---|---|
[Flask] 리다이렉트(Redirect) (0) | 2020.08.01 |
[Flask] Flask 시작 하기 (0) | 2020.07.29 |
Comments