Python HTTPServer responding to curl but not to Postman GET request - python-3.x

Consider a simple server in Python3 with the module BaseHTTPRequestHandler.
import json
import urllib.parse
from http.server import BaseHTTPRequestHandler, HTTPServer
import bson.json_util
class GetHandler(BaseHTTPRequestHandler):
def do_GET(self):
print("/n=================================")
json_string = '{"hello":"world"}'
self.wfile.write(json_string.encode())
self.send_response(200)
self.end_headers()
return
if __name__ == '__main__':
#from BaseHTTPServer import HTTPServer
server = HTTPServer(('localhost', 3030), GetHandler)
print ('Starting server, use <Ctrl-C> to stop')
server.serve_forever()
This is responding correctly with curl from the Terminal:
curl -i http://localhost:3030/
However when trying to send a request from Postman it is not responding. I tried the URL localhost:3030/, http://localhost:3030/ and also with the loopback address.
Why is that?

In all the examples I have seen it was not specifying the content type so I did the same way and seeing that curl worked I did not worry too much.
However content type should be specified: adding these lines before self.wfile.write(...)solves the problem:
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
Please note that actually self.send_response(200) has been moved, not added.

Related

How do I solve page not found error in flask rest api

I have developed a flask application that returns some text from OPEN-AI by giving some inputs.
But unfortunately the rest API in my application returns 404 error.
Here is the code:
from crypt import methods
from warnings import catch_warnings
from flask import Flask,request
from flask_cors import CORS
import flask
import openai
from flask_restful import Api,Resource
import base64
import json
#Init
app = Flask(__name__)
CORS(app)
api = Api(app)
app.run(host='0.0.0.0',port=8080)
#OPENAI CREDENTIALS
openai.api_key = ""
#Functions
class advert(Resource):
def post(self):
try:
request_body=request.json
A=request_body["data"]
adprompt = "Write an advertisement for " + A
response = openai.Completion.create(
engine="text-davinci-002",
prompt=adprompt,
temperature=0.7,
max_tokens=70,
top_p=1.0,
n=1
)
json_advert = json.loads(str(response))
advert_output = json_advert['choices'][0]['text']
to_return= json_advert = json.loads(str(advert_output))
return to_return,200
except:
return ({"ERROR":"Error Occured"}),500
#Mapping
api.add_resource(advert,'/data',methods=['POST'])
if __name__=='__main__':
app.run(debug=True)
This is the response i get:
192.168.1.21 - - [24/Nov/2022 11:52:59] "POST /data HTTP/1.1" 404 -
I've tried changing the port and endpoints, nothing helped .
How to solve this.
Your problem is at this line,
app.run(host='0.0.0.0',port=8080)
take it out, then add the parameters into the last line,
if __name__=='__main__':
app.run(debug=True, host='0.0.0.0',port=8080)
A bit more explanation, when the code hits app.run, it actually starts the server and not running the line api.add_resource. Hence, no path was configured.

How to return 401 in flask despite authorization

I am new to flask and I want to return 401 error, I am not using authentication, I am simply using a parameter api_key to check whether the user is authenticated.
I've tried abort(401) and return false, but it returns error 400 'Bad Request', is this the default way it returns a 401. Or is there a different way to do this?
My Code:
import flask
from flask import jsonify, request, Response
from flask_cors import CORS, cross_origin
from GoogleNews import GoogleNews
googlenews = GoogleNews()
googlenews.set_lang('en')
googlenews.set_period('1d')
googlenews.set_encode('utf-8')
app=flask.Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#cross_origin()
#app.route('/', methods=["GET"])
def return_news():
API_KEY = request.args['api_key']
if API_KEY == "xyz":
googlenews.get_news('TECHNOLOGY')
return jsonify(googlenews.result(True)[0:4])
else:
return Response(response="Unauthorized", status=401)
Thankyou
instead, try flask.Response object.
from flask import Flask, Response
app = Flask(__name__)
#app.route("/abort")
def abort():
return Response(response="Unauthorized", status=401)
app.run()
without the actual code it is hard to tell, but I think it is not using the flask abort() but the python internal abort() function.
Check the code below:
import flask
app = flask.Flask("aborter")
#app.route("/abort")
def abort():
return flask.abort(401)
if __name__ == '__main__':
app.run()
Happy Coding

Handling POST requests with http.server module

I'm using Python 3.7.4 and http.server module to receive POST requests that contain a file from an ERP.
Everything works fine (file get received and written correctly) except ERP get connection timeout error.
It's first time I use http.server which looks pretty simple but for sure I'm missing something.
See code below, isnt't "self.send_response(200)" enough?
On ERP vendor website they provide an example in PHP to receive data:
if (move_uploaded_file ($_FILES['file']['tmp_name'], "items.xml")){
echo "OK";
} else {
echo "Error";
}
So ERP expect "OK" after successful connection/transfer
Here it is my Python code:
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
import cgi
class Test_Server(BaseHTTPRequestHandler):
def do_POST(self):
print("POST request received")
self.send_response(200)
form = cgi.FieldStorage(fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers['Content-Type'],})
f = open("data/test-orig.xml","wb+")
f.write(form['file'].value)
f.close()
httpd = HTTPServer((hostName, hostPort), Test_Server)
print(time.asctime(), "Server Starts - %s:%s" % (hostName, hostPort))
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
print(time.asctime(), "Server Stops - %s:%s" % (hostName, hostPort))
Best regards,
cid
Manage to do it easily with Flask:
from flask import Flask
from flask import request
app = Flask(__name__)
#app.route('/post-data', methods=['POST'])
def test_server():
data = request.files['file']
data.save('data/test.xml')
return "OK"
if __name__ == '__main__':
app.run(host='0.0.0.0')
Solved!

aiohttp test with several servers

Trying to do a test that communicates with several instances of a web-server (which also communicates between them). But the second one seems to override the first however I try. Any suggestions of how to solve this.
So far I have this:
import os
from aiohttp.test_utils import TestClient, TestServer, loop_context
import pytest
from http import HTTPStatus as hs
from mycode import main
#pytest.fixture
def cli(loop):
app = main(["-t", "--location", "global", "-g"])
srv = TestServer(app, port=40080)
client = TestClient(srv, loop=loop)
loop.run_until_complete(client.start_server())
return client
#pytest.fixture
def cli_edge(loop):
app = main(["-t", "--location", "edge", "-j", "http://127.0.0.1:40080"])
srv = TestServer(app, port=40081)
client = TestClient(srv, loop=loop)
loop.run_until_complete(client.start_server())
return client
async def test_edge_namespace(cli, cli_edge):
resp = await cli.put('/do/something', json={})
assert resp.status in [hs.OK, hs.CREATED, hs.NO_CONTENT]
resp = await cli_edge.get('/do/something')
assert resp.status in [hs.OK, hs.CREATED, hs.NO_CONTENT]
The above call to cli.put goes to the server intended for cli_edge. I will have several more tests that should communicate with the servers.
Using Python 3.7 and pytest with asyncio and aiohttp extensions.
The suggested code works, the error was elsewhere in the server implementation.
You can add:
def fin():
loop.run_until_complete(srv.close())
loop.run_until_complete(client.close())
request.addfinalizer(fin)
and the request param in the pytest fixtures to close connections nicely.

Try to use ZnServer for GET and POST requests

Sorry for asking a possibly dumb question, but after reading documentation, looking at examples, etc., I still didn't find a solution for what I'm trying to do.
I used Pythons web server as a part of a larger project. It serves static files via do_GET method and can handle POST requests (sent by the client using XMLHTTPRequest) via do_POST method. Everything is working well.
What I'm trying to do is an implementation of the web server in Pharo. I think that ZnServer (part of Pharo 2.0) is the way to go. It must be able to serve static files and handle POST requests.
Python code for a very simple http server example
# httpd_test.py
# Imports
import os
import sys
import cgi
import json
from BaseHTTPServer import BaseHTTPRequestHandler
from BaseHTTPServer import HTTPServer
# HTTP Request Handler Class
class RequestHandler(BaseHTTPRequestHandler):
# Process GET requests
def do_GET(self):
print(self.path)
# Send response
tex = 'GET: ' + self.path
self.send_response(200)
self.send_header('Content-type','text/plain')
self.send_header('Content-length',str(len(tex)))
self.end_headers()
self.wfile.write(tex)
self.wfile.flush()
# Process POST requests
def do_POST(self):
# Read CGI data
CgiData = cgi.FieldStorage(fp = self.rfile,
headers = self.headers,
environ = {'REQUEST_METHOD':'POST',
'CONTENT_TYPE':self.headers['Content-Type']})
# Invoke action
if self.path == '/handler':
print(repr(CgiData))
else:
print('Unknown POST handler.')
print(repr(CgiData))
# Send response
self.send_response(200)
tex = repr(CgiData)
self.send_header('Content-type','text/plain')
self.send_header('Content-length',str(len(tex)))
self.end_headers()
self.wfile.write(tex)
self.wfile.flush()
# Start Server
if __name__ == '__main__':
server = HTTPServer(('127.0.0.1',8080),RequestHandler)
server.serve_forever()
What I have tried in Pharo (but with no luck)
start
"Start ZnServer default"
| staticFileServerDelegate |
ZnServer startDefaultOn: 8080.
(ZnServer default) logToTranscript.
(ZnServer default) authenticator: (ZnBasicAuthenticator username: 'foo' password: 'bar').
staticFileServerDelegate := ZnStaticFileServerDelegate new.
staticFileServerDelegate prefixFromString: 'zn';
directory: 'C:\Temp'.
" (ZnServer default) delegate prefixMap
at: 'zn'
put: [ :request | staticFileServerDelegate handleRequest: request ];
at: '/'
put: [ :request | ZnResponse redirect: 'C:\Temp' ]."
(ZnServer default) delegate prefixMap
at: '/'
put: [ :request | Transcript cr; show:'1 '; show: request; cr. ];
at: 'handler'
put: [ :request | Transcript cr; show:'3 '; show: request; cr. ].
"start" is a class method of an own class with no base class.
I'm a newbie to Pharo, so it's possible that I'm on the wrong track.
I hope, the description is clear enough, so one can see what I want to do.
Any help on this would be highly appreciated.
Thanks in advance.
As a default server, this should work:
(ZnServer startDefaultOn: 8080)
onRequestRespond: [ :request |
ZnResponse ok: (ZnEntity text: 'Hiya!') ].
Then you can manage the documents answered on ZnResponse.
But why don't you use something more powerful like Seaside? http://seaside.st

Resources