Home > Blockchain >  http post request response from localhost in python
http post request response from localhost in python

Time:04-25

Many questions regarding http post requests, but I can't make a complete example running.

$ tree
.
└── src
    └── main.py # <----- this is the file I want to send data to
$ cat src/main.py
from typing import Dict, List
class Handler: # <----- (Probably should inherit from some class ?!)
    def post(self, data: Dict[str, int]) -> List[str]:
        return "   ".join([k for k in data])
$ python -m http.server 8001

Now I try to send data (from some other terminal)

$ cat send_something.py
import requests
x = requests.post("http://localhost:8001/src/main.py", data={"name": 700, "id": 99})
print(x)

And I get a 501 response which means I'm doing something wrong:

$ python send_something.py
<Response [501]>

On the localhost server I do see the post request, but with an error message:

127.0.0.1 - - [20/Apr/2022 09:29:22] code 501, message Unsupported method ('POST')
127.0.0.1 - - [20/Apr/2022 09:29:22] "POST /src/main.py HTTP/1.1" 501 -

Any help is very much appreciated, thanks.

CodePudding user response:

Turns out I was missing many things. Here is the server code. It will receive json data and tweak it a bit as proof of concept.

import json

from typing import List

from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler

from attrs import asdict
from attrs import define

HOST = "127.0.0.1"
PORT = 8027 # <----- nailed it in the 27th try :)

@define
class Entry:

    name: str
    some_list: List[int]

class Handler(BaseHTTPRequestHandler):
    def do_POST(self):
        
        # read incoming sent data
        data = self.rfile.read(self._sent_data_size)
        
        # do something with it ...
        response = self._process(data.decode("utf-8"))

        # perpare the (json) response
        jsonbytes = self._prepare_json_response(response)
                    
        # send the (json) response back ...
        self.wfile.write(jsonbytes)

    def _process(self, data: str) -> List[Entry]:
        return [
            Entry("employee" str(i), [d["id"], d["salary"]])
            for i, d in enumerate(json.loads(data))
        ]

    def _prepare_json_response(self, response: List[Entry]) -> bytes:
        self.send_response(200)
        self.send_header("Content-type", "application/json")
        self.end_headers()
        jsonstr = json.dumps(
            response,
            indent=4,
            default=asdict
        )
        return jsonstr.encode()

    @property
    def _sent_data_size(self) -> int:
        return int(self.headers.get("Content-Length"))

server = HTTPServer((HOST, PORT), Handler)
server.serve_forever()
server.serve_close()

Here is the client code:

import requests

with open("input.json") as fl:
    data = json.load(fl)

x = requests.post("http://localhost:8027", json=data)
print(x.json())

The server is started, then the client sends the json data (from another terminal). the client receives the tweaked json properly and that's the happy end.

  • Related