Accept parameters only from POST request in python - python

Is there a way to accept parameters only from POST request?
If I use cgi.FieldStorage() from cgi module, it accepts parameters from both GET and POST request.

By default, most things in the cgi module merge os.environ['QUERY_STRING'] and sys.stdin (in the format suggested by os.environ['CONTENT_TYPE']). So the simple solution would be to modify os.environ, or rather, provide an alternative, with no query string.
# make a COPY of the environment
environ = dict(os.environ)
# remove the query string from it
del environ['QUERY_STRING']
# parse the environment
form = cgi.FieldStorage(environ=environ)
# form contains no arguments from the query string!
Ignacio Vazquez-Abrams suggests avoiding the cgi module altogether; modern python web apps should usually adhere to the WSGI interface. That might instead look like:
import webob
def application(environ, start_response):
req = webob.Request(environ)
if req.method == 'POST':
# do something with req.POST
# still a CGI application:
if __name__ == '__main__':
import wsgiref.handlers
wsgiref.handlers.CGIHandler().run(application)

From the documentation, I think you can do the following:
form = cgi.FieldStorage()
if isinstance(form["key"], cgi.FieldStorage):
pass #handle field
This code is untested.

Related

How to pass an HTTP request as a parameter of a python function?

I'm calling a python function and passing an HTTP request as a parameter but it's not working. I created the function in a View and called it in another, but the parameter fails.
Here's the function I'm calling
def load_colmeias(request):
apiario = request.GET.get('apiario')
if apiario != "":
colmeias = Colmeia.objects.filter(apiario=apiario)
return render(request, 'colmeias_choices.html', {'colmeias': colmeias})
else:
return render(request, 'colmeias_choices.html')
Here I call her
load_colmeias(request)
But the following error occurs
NameError: name 'request' is not defined
I already imported the "urlib" and "requests" libraries but it always gives the same error:
AttributeError: module has no attribute 'GET'
Can someone help me ?? I'm new to Python/Django and I'm still learning how to do things
Check if you have requests installed:
import requests
r=requests.get("https://automatetheboringstuff.com/files/rj.txt")
print(len(r.text))
Now, check:
In load_colmeias(request), make sure the parameter is actually request and not requests throughout.
Your filename is not requests.py; otherwise you would be importing your own file.
request and requests are two different things, one without 's' is a parameter and with 's' is a method. to use requests you have to import requests library this is a third party library to fetch data from an API.
if you want to call this function you have to make a request through an API. create an API for this function and then make a request.
your views.py file:
def load_colmeias(request):
apiario = request.GET.get('apiario')
if apiario != "":
colmeias = Colmeia.objects.filter(apiario=apiario)
return render(request, 'colmeias_choices.html', {'colmeias': colmeias})
else:
return render(request, 'colmeias_choices.html')
Your urls.py file:
from django.urls import path
from . import views
urlpatterns = [
path('load_colmeias', views.load_colmeias)
]
Now your API is:
http://127.0.0.1:8000/load_colmeias?apiario=1234
make sure you have used the correct port in the api and have started the server before making the request and pass the correct value of apiario.
There is another way to call this function by using requests library:
import requests
res = requests.get('http://127.0.0.1:8000/load_colmeias?apiario=1234')
print(res.text)
you can use this in any file and call your function like this using this library again the server must be running and pass the correct value of apiario.
Well if you are passing a request parameter then you have to make the request. You can't call it the way you have shown.
I SOLVED THE PROBLEM !! Basically, I just created a function that calls another function and passed the same argument to both... As can be seen below:
def load_colmeias(request):
return carregar_colmeia(request)
I don't know if it's recommended, but it solved my problem of having to rewrite the same code in multiple views.

flask-apispec not populating kwargs with values from GET query (implementation of example code from documentation)

I am using flask-apispec with webargs to define the types of a simple API. I have produced a minimal example, below, that reproduces the issue, which is that the kwargs object is empty.
Server code:
import flask
from flask_apispec import use_kwargs
from webargs import fields
app = flask.Flask(__name__)
#app.route('/pets', methods=["GET"])
#use_kwargs({'species': fields.Str()})
def list_pets(**kwargs):
assert False, kwargs # NO DATA HERE
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Simple client script:
import requests
requests.get("http://localhost:5000/pets", params={"species": "cat"})
Why is the kwargs dict empty? I don't see how the above is at all different from the example in the flask-apispec documentation.
I had the same problem and suffered a little with the documentation.
Referencing webargs docs (that is what I understood flask-apispec uses under the hood) I found some examples and was able to implement it.
The location parameter is what was missing.
In your example it would be:
#app.route('/pets', methods=["GET"])
#use_kwargs({'species': fields.Str()}, location="query")
def list_pets(**kwargs):
print(kwargs) # Now "species" should be here if sent through the query
I'm using flask-apispec v0.11.1, which installed webargs v8.1.0 on my system.

python django soaplib response with classmodel issue

I run a soap server in django.
Is it possible to create a soap method that returns a soaplib classmodel instance without <{method name}Response><{method name}Result> tags?
For example, here is a part of my soap server code:
# -*- coding: cp1254 -*-
from soaplib.core.service import rpc, DefinitionBase, soap
from soaplib.core.model.primitive import String, Integer, Boolean
from soaplib.core.model.clazz import Array, ClassModel
from soaplib.core import Application
from soaplib.core.server.wsgi import Application as WSGIApplication
from soaplib.core.model.binary import Attachment
class documentResponse(ClassModel):
__namespace__ = ""
msg = String
hash = String
class MyService(DefinitionBase):
__service_interface__ = "MyService"
__port_types__ = ["MyServicePortType"]
#soap(String, Attachment, String ,_returns=documentResponse,_faults=(MyServiceFaultMessage,) , _port_type="MyServicePortType" )
def sendDocument(self, fileName, binaryData, hash ):
binaryData.file_name = fileName
binaryData.save_to_file()
resp = documentResponse()
resp.msg = "Saved"
resp.hash = hash
return resp
and it responses like that:
<senv:Body>
<tns:sendDocumentResponse>
<tns:sendDocumentResult>
<hash>14a95636ddcf022fa2593c69af1a02f6</hash>
<msg>Saved</msg>
</tns:sendDocumentResult>
</tns:sendDocumentResponse>
</senv:Body>
But i need a response like this:
<senv:Body>
<ns3:documentResponse>
<hash>A694EFB083E81568A66B96FC90EEBACE</hash>
<msg>Saved</msg>
</ns3:documentResponse>
</senv:Body>
What kind of configurations should i make in order to get that second response i mentioned above ?
Thanks in advance.
I haven't used Python's SoapLib yet, but had the same problem while using .NET soap libs. Just for reference, in .NET this is done using the following decorator:
[SoapDocumentMethod(ParameterStyle=SoapParameterStyle.Bare)]
I've looked in the soaplib source, but it seems it doesn't have a similar decorator. The closest thing I've found is the _style property. As seen from the code https://github.com/soaplib/soaplib/blob/master/src/soaplib/core/service.py#L124 - when using
#soap(..., _style='document')
it doesn't append the %sResult tag, but I haven't tested this. Just try it and see if this works in the way you want it.
If it doesn't work, but you still want to get this kind of response, look at Spyne:
http://spyne.io/docs/2.10/reference/decorator.html
It is a fork from soaplib(I think) and has the _soap_body_style='bare' decorator, which I believe is what you want.

webpy: How to serve JSON

Is it possible to use webpy to serve JSON?
I built my website and I need to serve some information in JSON to interact with the Javascript on some pages.
I try to look for answers in the documentation, but I'm not able to find anything.
Thanks,
Giovanni
I wouldn't think you'd have to do any thing overly "special" for web.py to serve JSON.
import web
import json
class index:
def GET(self):
pyDict = {'one':1,'two':2}
web.header('Content-Type', 'application/json')
return json.dumps(pyDict)
It is certainly possible to serve JSON from webpy, But if you and choosing a framework, I would look at starlight and my fork twilight (for documentation).
It has a JSON wrapper for fixing the http headers for your json response.
it uses either the json or simplejson libraries for json handling the conversions to and from other objects.
I am using it right now and it is great.
https://bitbucket.org/marchon/twilight
in it you will find an example called ShowMeTheJson.py
that uses simple json
from starlight import *
from werkzeug.routing import Map
from werkzeug.routing import RuleFactory
import simplejson
class ShowMeTheResponses(App):
####################################################################
#
# Sample URLS to Test Responses
#
# http://localhost:8080/ root
#
# http://localhost:8080/json return JSON Mime Type Doc
#
###################################################################
#default
def hello(self):
return 'Hello, world!'
#dispatch('/')
def index(self):
return 'Hello Root!'
#dispatch('/html')
def indexhtml(self):
return HTML('Hello HTML')
#dispatch('/json')
def indexjson(self):
directions = {'N' : 'North', 'S' : 'South', 'E':'East', 'W' : 'West'}
return JSON(simplejson.dumps(directions))
if __name__ == '__main__':
from werkzeug import run_simple
run_simple('localhost', 8080, ShowMeTheResponses())

Specifying custom URL schema in appengine using app.yaml?

I am trying to have a custom URL which looks like this:
example.com/site/yahoo.com
which would hit this script like this=
example.com/details?domain=yahoo.com
can this be done using app.yaml?
the basic idea is to call "details" with the input "yahoo.com"
You can't really rewrite the URLs per se, but you can use regular expression groups to perform a similar kind of thing.
In your app.yaml file, try something like:
handlers:
- url: /site/(.+)
script: site.py
And in your site.py:
SiteHandler(webapp.RequestHandler):
def get(self, site):
# the site parameter will be what was passed in the URL!
pass
def main():
application = webapp.WSGIApplication([('/site/(.+)', SiteHandler)], debug=True)
util.run_wsgi_app(application)
What happens is, whatever you have after /site/ in the request URL will be passed to SiteHandler's get() method in the site parameter. From there you can do whatever it is you wanted to do at /details?domain=yahoo.com, or simply redirect to that URL.

Categories