TigerCow.Door

지난 번에 이어서 토네이도(Tornado) 공부를 진행하겠습니다.

이번 포스팅에서는

Request handler and Request argument 에 대해서 공부를 진행합니다.


토네이도 웹 어플리케이션은 URL 또는 URL 패턴을 tornado.web.RequestHandler의 subclass(서브클래스)로 매핑합니다.

이 클래스들은 해당 URL로의 HTTP GET 또는 POST request를 처리하기 위한 get() 또는 post() 메소드를 정의합니다.


지난 시간에 진행했던 기본 테스트 예제를 먼저 확인하겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# from : http://www.tornadoweb.org/en/stable/#hello-world
# myapp.py
import tornado.ioloop
import tornado.web
 
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")
 
def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])
 
if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()
cs


6번 라인을 확인하면 MainHandler 가 존재합니다.

12번 라인을 확인하면 URL인 '/' 는 MainHandler에 매핑되고 있습니다.


다른 예제를 통해 한번 더 확인하겠습니다.

아래 코드는 URL인 '/'는 MainHandler에, URL 패턴인 '/story/([0-9]+)' 는 StoryHandler 로 매핑하고 있습니다.

정규식(regular expression) 그룹은 Requesthandler 메소드에게 argument로 전달됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import tornado.httpserver 
import tornado.ioloop 
import tornado.web
 
class MainHandler(tornado.web.RequestHandler):     
     def get(self):         
          self.write("You requested the main page")
 
class StoryHandler(tornado.web.RequestHandler):     
     def get(self, story_id):         
          self.write("You requested the story " + story_id) 
 
application = tornado.web.Application([     
     (r"/", MainHandler),     
     (r"/story/([0-9]+)"
     StoryHandler), 
]) 
 
if __name__ == "__main__":     
     http_server = tornado.httpserver.HTTPServer(application)           
     http_server.listen(8888)    
     tornado.ioloop.IOLoop.instance().start()
cs


빨간색 동그라미를 확인하면 MainHandler 매핑되는 '/' 를 확인할 수 있다.



빨간색 동그라미를 확인하면 StoryHandler 매핑되는 '/story/([0-9]+)' 를 확인할 수 있다.





또한 get_argument () 메소드를 사용하면 query string 을 가져와서 POST 바디의 내용을 파싱할 수 있습니다.

코드와 실행결과는 아래와 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import tornado.httpserver 
import tornado.ioloop 
import tornado.web 
 
class MainHandler(tornado.web.RequestHandler):     
     def get(self):         
          self.write('<html><body><form action="/" method="post">'                    
                    '<input type="text" name="message">'                    
                    '<input type="submit" value="Submit">'
                    '</form></body></html>')    
 
     def post(self):         
          self.set_header("Content-Type""text/plain")         
          self.write("You wrote " + self.get_argument("message"))
 
application = tornado.web.Application([     
     (r"/", MainHandler),   
]) 
 
if __name__ == "__main__":     
     http_server = tornado.httpserver.HTTPServer(application)
     http_server.listen(8888)     
     tornado.ioloop.IOLoop.instance().start()
cs


코드의 7~10 라인을 통해 input 칸과 button이 만들어짐을 확인할 수 있다.

input의 이름은 message로 설정되어 있다.

form tag로 묶여있으며 form tag의 내부를 확인하면 post 방식으로 데이터를 보낸다.



따라서 버튼을 누르면 input 에 입력된 값이 post 방식으로 '/' 주소로 넘어가며

그때 넘어가는 데이터의 이름은 message 이다.

12번 라인의 post 함수를 보면 이를 받아 페이지를 구성하는 것을 알 수 있다.

14번 라인에서 message 라는 argument를 얻어서 

You wrote ~ 을 만들어 낸다.



클라이언트에 에러 response ( 예를들면 403 Unauthorized 같은 ) 를 보내려면

tornado.web.HTTPError exception을 raise해주면 됩니다.


1
2
if not self.user_is_logged_in():     
     raise tornado.web.HTTPError(403)
cs


request handler에서 현재 request 오브젝트를 self.request로 access할 수 있습니다.

HTTPRequest 오브젝트는 여러가지 유용한 attribute를 포함하고 있습니다.


▶ arguments - GET 과 POST의 전체 argument

▶ files - (multipart/form-data POST request를 통한) 모든 업로드 된 파일들

▶ path - request 패스 (URL 에서 '?' 앞쪽 전체)

▶ headers - request 헤더


모든 attribute 목록은 httpserver의 HTTPRequest 클래스 정의를 확인하면 됩니다.



이상으로 Tornado에서 Request handler and request argument 에 대한 포스팅을 마치도록 하겠습니다.

궁금한 점이 있거나 추가적인 도움을 주고싶으신 분이 있다면

댓글이나 doorBW@outlook.com 을 통해 메일주세요!

블로그 이미지

Tigercow.Door

Back-end / Python / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요