pythonfalconframeworkfalcon

Python Falcon - Post calls are being ignored


I'm trying to set up a simple reverse proxy with Falcon in Python.

I have:

import falcon
import requests

class ReverseProxyResource:
    def on_get(self, req, resp, text=None):
        print("GET")
        if(text):
            destination = "[destination_url]/" + text
        else:
            destination = "[destination_url]"
        result = requests.get(destination)
        resp.body = result.text
        resp.status = result.status_code 

    def on_post(self, req, resp, text=None):
        print("POST")
        if(text):
            destination = "[destination_url]/" + text
        else:
            destination = "[destination_url]"
        result = requests.post(destination, data=req.bounded_stream.read())
        resp.body = result.text
        resp.status = result.status_code 

proxy_api = application = falcon.API()
proxy_api.req_options.auto_parse_form_urlencoded = True
proxy_api.add_route('/{text}', ReverseProxyResource())
proxy_api.add_route('/', ReverseProxyResource())

Get requests to the proxy are returned correctly.

However, Post requests are only returned a 404 error from the api. The "POST" print statement is not shown, indicating on_post isn't called at all. (The post requests only included Header Content-Type: application/json and a simple JSON body, which work correctly when called directly against the destination url)

EDIT: Interestingly enough, if I change GET call in postman to POST (ie: no body, headers, or anything else added) on_post() is called when I hit the endpoint. So it seems like an issue where post requests that contain a body are being automtically 404'ed without calling on_post()


Solution

  • Try adding user agent and content type before making the post call

    headers = {"Content-Type": "text/plain", "User-Agent": "PostmanRuntime/7.30.0"}
    result = requests.post(url = destination, data=req.bounded_stream.read(), headers=headers)
    

    below code works for me

    import falcon
    import requests
    
    class ReverseProxyResource:
        def on_get(self, req, resp, text=None):
            print("GET")
            if(text):
                destination = "https://cat-fact.herokuapp.com/" + text
            else:
                destination = "https://cat-fact.herokuapp.com/facts/"
            result = requests.get(destination)
            resp.body = result.text
            resp.status = result.status_code
    
        def on_post(self, req, resp, text=None):
            print("POST")
            if(text):
                destination = "https://dummy.restapiexample.com/api/v1/"+ text
            else:
                destination = "https://dummy.restapiexample.com/api/v1/create"
            headers = {"Content-Type": "text/plain", "User-Agent": "PostmanRuntime/7.30.0"}
            result = requests.post(url = destination, data=req.bounded_stream.read(), headers=headers)
            resp.text = result.text
            resp.status = result.status_code
    
    proxy_api = application = falcon.App()
    proxy_api.req_options.auto_parse_form_urlencoded = True
    proxy_api.add_route('/{text}', ReverseProxyResource())
    proxy_api.add_route('/', ReverseProxyResource())