티스토리 뷰

[Rails][Web API] Post 요청 처리하기


웹 API 제작을 하는 관점에서 레일즈에서 응답코드를 넣어 반응하는 것이 클라이언트에서 처리를 할 때도 용이하고 바람직합니다.


앞 전 게시글에서 JSON 혹은 XML로의 응답에 대해 다루어 보았습니다. 이번에는 Post, Put, Patch 그리고 Delete 중 Post의 처리 방법을 살펴보겠습니다.



POST METHOD 처리

POST 처리 시에 201 HTTP 응답코드를 이용하는 것이 바람직합니다. 201 상태응답은 다음과 같습니다:

201 Created

새로운 URI가 만들어질 때마다 사용되며 결과 코드와 함께 새로운 데이터가 위치한 곳을 지정하기 위해 Location 헤더가 서버에 의해 주어집니다. 원 서버는 201 상태 코드를 리턴하기 전에 반드시 자원을 생성해야 합니다. 처리가 즉각적으로 수행될 수 없을 때에 서버는 202(Accept) 응답으로 대신 응해야합니다.

출처: http://www.coolcheck.co.kr/upload/http_scode.asp


다음으로 201 상태코드에 맞는 예제코드를 살펴보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
class EpisodesController < ApplicationController
    def create
        episode = Episode.new(episode_params)
        if episode.save
            render json: episode, status: 201, location: episode
        end
    end
 
    private
    def episode_params
        params.require(:episode).permit(:title, :description)
    end
end
cs


status: 201 대신에 status: :created 를 사용하도 됩니다. location: 부분에 예제와 같이 해당 리소스의 url을 넣으면 됩니다.


하지만 이대로 사용을하면 레일즈의 FORGERY PROTECTION 때문에 422 (Unprocessable Entity) 응답이 옵니다. 이를 해결하기 위해서는 application_controller.rb를 다음과 같이 수정해줘야 합니다.


app/controllers/application_controller.rb

1
2
3
4
5
6
class ApplicationController < ActionController::Base  
    # Prevent CSRF attacks by raising an exception.  
    # For APIs, you may want to use :null_session instead.  
    # protect_from_forgery with: :exception
    protect_from_forgery with: :null_session
end
cs


이렇게 수정하면  POST 요청이 오면 authenticity token 을 무시하고 세션을 사용하지 않게 됩니다. 정상적으로 생성이 되게 됩니다.


다음과 같이 리눅스 계열의 curl 명령어로 테스트해볼 수 있습니다.

$ curl -i -X POST -d 'episode[title]=test' http://localhost:3000/episodes



body 없이 응답하기

만약, 속도 상의 문제로 응답의 body 부분 없이 반응 하려면 204 HTTP 응답코드를 사용하시면 됩니다. 이 경우 head 함수를 이용하여 처리할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class EpisodesController < ApplicationController    
    def create        
        episode = Episode.new(episode_params)  
        if episode.save            
            head 204, location: episode      
        end    
    end     
 
    private    
    def episode_params        
        params.require(:episode).permit(:title, :description)    
    end
end

cs


head 204 는 head :no_content 로도 사용할 수 있습니다.



예외처리하기

예외 처리는 422 응답코드를 이용하여 처리하면됩니다.

1
2
3
4
# app/models/episode.rb
class Episode < ActiveRecord::Base
    validates :title, presence: true
end
cs

위와같이 validation이 있다고 가정합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class EpisodesController < ApplicationController    
    def create        
        episode = Episode.new(episode_params)  
        if episode.save            
            render json: episode, status: :created, location: episode
        else
            render json: episode.errors, status: 422
        end    
    end     
 
    private    
    def episode_params        
        params.require(:episode).permit(:title, :description)    
    end
end
cs


서버 내부의 에러의 경우 레일즈에서 500 에러응답을 자동으로 처리해줍니다.

댓글