본문 바로가기
웹(web)/백엔드-python

do_GET+ do_POST 예제2

by 바코94 2020. 7. 1.

예제 1에서는 localhost:8000을 입력해서 들어가면 

위와 같은 입력 폼이 나오고 Post it을 누르면 썼던 내용이 화면에 나타나는 예제였다. 

Hello world!를 쓰고 Post it 버튼을 눌렀을 때 다음과 같이 나오려면 어떻게 해야할까?

또한, 한 번 더 Hello World2!를 쓰고 Post it을 눌렀을 때 다음과 같이 나오려면 어떻게 해야할까?

 

별도의 데이터베이스 없이 위와 같은 기능을 구현하려면 어떻게 해야할까?

예제 1을 다시 생각해보면 form을 만들고, do_GET을 구현하고, do_POST를 구현하면 끝이었다. 각각의 기능은 서로 영향을 미치지 않고 독립적이다. 

 

새로운 예제2의 상황을 정리해보면 아래와 같은 흐름으로 진행된다.

1. localhost:8000에 접속하면 입력폼이 주어진다.

2. 데이터를 Post 방식으로 보낸다.

 

3. 입력폼과 2에서 보낸 데이터가 같이 나온다.

4. 데이터를 Post 방식으로 보낸다.

 

5. 입력폼과 2,4에서 보낸 데이터가 같이 나온다.

6. 데이터를 Post 방식으로 보낸다.

 

위 상황을 요약해보면

1,3,5는 입력폼 + 누적된 데이터가 같이 나온다. 1에서는 누적된 데이터가 없다고 생각할 수 있다.

2,4,6에서 보내진 데이터는 어딘가에 누적되어진다.

 

따라서 누적하는 데이터를 저장하는 변수를 하나 만들어서 관리하면 될 것이다. 또한 Get에서는 폼과 누적된 데이터를 함께 응답으로 보낸다. Post에서는 데이터가 들어올 때마다 기존 변수에 추가해주면 될 것이다. 

여기서 중요한 것은 Post에서 데이터를 누적하고 localhost:8000으로 Get 요청을 보낸 것과 같은 결과를 보여주어야 한다. 이를 위해 Post에 대한 응답으로 localhost:8000에 대한 GET요청을 다시 하도록 클라이언트에게 전달해주면 된다. 이런 것을 redirection이라고 한다. HTTP 상에서는 POST에 대한 응답으로 303 응답과 URL을 보내면 클라이언트 측에서 해당 URL로 GET 요청을 보내는 방식으로 작동한다.

 

그렇다면 구현하는 코드를 살펴보자.

1. 데이터를 저장하는 변수를 생성

memory = []

 

2. GET 응답으로 보낼 데이터를 생성. '''은 여러 줄의 string 임을 나타냄. pre 요소의 {}는 format을 사용해서 데이터가 들어갈 위치

form = '''<!DOCTYPE html>
  <title>Message Board</title>
  <form method="POST">
    <textarea name="message"></textarea>
    <br>
    <button type="submit">Post it!</button>
  </form>

  <pre>{}</pre>'''

 

3. do_GET은 헤더 설정하고  form.format()을 사용하여 {} 부분에 memory를 위치시킴. memory는 리스트이므로 join을 통해 스트링으로 만들어줌.

3.1 헤더 설정

self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()

 

3.2 응답 메세지 설정

mesg = form.format("\n".join(memory)) 
self.wfile.write(mesg.encode())

 

4. do_POST는 entity body에서 message 필드의 데이터를 가져와 memory에 추가함. 응답으로 303과 redirect URI를 줌.

4.1 데이터 가져오기

length = int(self.headers.get('Content-length', 0))  
data = self.rfile.read(length).decode()

message = parse_qs(data)["message"][0]

 

4.2 가져온 데이터에서 "<" 기호는 &lt로 변경. 이유는 화면에 보여질 때 tag가 아닌 text로만 인식하도록 하기위함.

message = message.replace("<", "&lt;")

 

4.3 메모리 변수에 데이터 추가

memory.append(message)

 

4.4 응답 코드 설정

self.send_response(303)

 

4.5 redirect url 설정. Location이 /라는 것은 root를 의미함. localhost:8000/ 로 리다이렉트 하라는 것을 의미
self.send_header('Location', '/')
self.end_headers()

 

예제 1과 동일하게 do_GET과 do_POST는 BaseHTTPRequestHandler를 상속받아 만든 클래스에 위치시킨다.

 

'웹(web) > 백엔드-python' 카테고리의 다른 글

CookieServer  (0) 2020.07.02
JSON  (0) 2020.07.02
do_GET+ do_POST 예제1  (0) 2020.07.01
parse_qs(POST data parsing)  (0) 2020.07.01
EchoServer  (0) 2020.07.01