webpy POST returns 405 Method Not Allowed - web.py

I am new to webpy and python, I just tested the basic GET and POST on my laptop.
Here is the code:
import web
urls = (
"/get", "get",
"/post", "post"
)
app = web.application(urls, globals())
class test:
def GET(self):
return "get"
class post:
def POST(self):
return "post"
if __name__ == "__main__":
app.run()
The GET works OK, but POST returns 405 Method Not Allowed error.
Anyone could give me a hand? Thanks.

When you check if POST is working are you actually sending/posting any data to the server? If you navigate to the url "/post" you will make a "GET" request to the server and since there is no GET function for that url it will return "405 Method Not Allowed".
So if you would like to make something like a form, you would have a GET function that returned the page to the user, and then a POST function to receive the input from the form and do something with it on the server. Both within the same url class.
Hope that helps.

Related

SoapUI 5.7.0 mockRequest.requestContent is empty for POST request

I am using SOAP UI 5.7.0 to mock a REST service and it is working fine. Only, when I want to access the body of a POST request with mockRequest.requestContent, the correct content is returned only in the first call, but from then on, it always returns the empty string.
I tried the call in OnRequestScript and in the POST requests own Dispatch script but the behavior is the same in both cases. I have the suspicion, that the Stream of the request is already read somewhere else and so does not return any more content. But I don't know what to do about it.
I wonder what is the correct way to read the content of a POST request.
Thank you
Appears to be a known issue, see posts in the community forum here and here.
this seems to be an old bug of PUT operation in REST mocks.
Unfortunately, this is a bug. There is an internal defect of SOAP-2344 for this issue. This applies for the PUT and DELETE methods for a REST mock service.
I have the same issue with a PATCH request.
Use the following trick to get the body of the PUT and DELETE requests:
mockRequest.with {
if (method.toString() == 'PUT' || method.toString() == 'DELETE') {
InputStreamReader isr = new InputStreamReader(request.getInputStream(), "UTF-8")
BufferedReader br = new BufferedReader(isr)
StringBuilder sb = new StringBuilder()
while ((s=br.readLine())!=null) {
sb.append(s)
}
def requestBody = new groovy.json.JsonSlurper().parseText(sb.toString())
log.info "requestBody: " + requestBody
}
}
I use it on the project but I don't really remember how where I got the snippet from. I had to change some parts to make it work as far as I remember. Give it a try.

validating response outside of context manager?

[EDITED: I realized after reading response that I oversimplified my question.]
I am new to Locust and not sure how to solve this problem.
I have function (call it "get_doc") that is passed a locust.HttpSession() and uses it to issue an HTTP request. It gets the response and parses it, returning it up several layers of call. One of these higher-level calls looks at the returned, parsed document to decide if the response was what was expected or not. If not, I want Locust to mark the request/response as failed. A code sketch would be:
class MyUser (HttpUser):
#task
def mytask(self):
behavior1 (self.client)
def bahavior1(session):
doc = get_doc(session, url1)
if not doc_ok (doc):
??? how to register a failure with Locust here...
doc2 = get_doc(session, url2)
...
def get_doc(http_session, url):
page = http_session.get(url)
doc = parse (page)
return doc
There may be several behavior[n] functions and several Locust users calling them.
A constraint is that I would like to keep Locust-specific stuff out of bahavior1() so that I can call it with an ordinary Requests session. I have tried to do something like this in get_doc() (the catch_response parameter and success/fail stuff is actually conditionalized on 'session' being an HttpSession object):
def get_doc (session, meth, url):
resp = session.request (meth, url, catch_response=True)
doc = parse (resp.content)
doc.logfns = resp.success, resp.failure
return doc
and then in behavior1() or some higher up-chain caller I can
doc.logfns[1]("Document not as expected")
or
doc.logfns[0] # Looks good!
Unfortunately this is not working; the calls to them produce no errors but Locust doesn't seem to record any successes or failures either. I am not sure if it should work or I bungled something in my code. Is this feasible? Is there a better way?
You can make get_doc a context manager, call .get with catch_response=True and yield instead of return inside it. Similar to how it is done here: https://github.com/SvenskaSpel/locust-plugins/blob/2cbbdda9ae37b6cbb0a11cf69aca80b164198aec/locust_plugins/users/rest.py#L22
And then use it like this
def mytask(self):
with get_doc(self.client, url) as doc:
if not doc_ok(doc):
doc.failure(”doc was not ok :(”)
If you want, you can add the parsed doc as a field on the response before yielding in your doc function, or call doc.failure() inside doc_ok.

getting url parameters in tornado

i've been facing some problems in getting url parameters using Tornado web framework.
these are my codes:
def main_app():
return tornado.web.Application([
(r"/reg", register),
(r"/account", account),
])
class account(tornado.web.RequestHandler):
def get(self):
name = self.get_argument('name')
depo = self.get_argument('depo')
respone = {'name':name ,'depo':depo}
self.write(respone)
i've tried to use some restful API to test this web service.
i curl a url like curl localhost:8000/account?name = "parsa" & depo = "10"
but always i get this error that says it doesn't recognize depo. actually i tested something and it showed that each time the second parameter doesn't work well or even the third one doesn't work.
i tried several ways but didn't work.
This is not a problem with your Tornado code. You are making the curl request incorrectly. You can verify that by visiting that url from your browser.
With, curl, you'll have to wrap the whole url in quotes:
curl "localhost:8000/account?name=para&depo=10"

Using Proxy Authorization Header with ScalajHTTP

I'm getting a 407 error using scalajHTTP. I read through the repository and it seems like I should be able to pass the basic auth credentials as a base64 encoded value. I've also tried using the helper method described in the GitHub issues .proxyAuth but that is no longer part of HTTPRequest in ScalaJ according to error messages (as well as it not being in the documentation)
Any ideas? My endpoint URL is HTTPS as well as my proxy (for additional context)
val proxyHost= s"https://$forwardProxy"
val requestForward = Http(url).postData(redactedSecret)
.option(HttpOptions.allowUnsafeSSL)
.headers(("Content-Type", "application/json"), ("Proxy-Authorization", s"Basic $proxyAuth"))
.proxy(proxyHost, 8080).asString
val responseForward: HttpResponse[String] = requestForward
This issued posted in Github but still not resolved, https://github.com/scalaj/scalaj-http/issues/87
I found a solution to this problem. I researched around and after trying http client libraries, I kept getting 407 errors even though they all support proxy auth. Anyway, I ended up having to do the following.
add
import java.net.{Authenticator,PasswordAuthentication}
and the modified code body that I previously above looks like:
val requestForward: HttpRequest = Http(url).postData(data)
.header("Content-Type", "application/json")
.proxy(proxyHost, 8080)
.option(HttpOptions.allowUnsafeSSL)
Authenticator.setDefault(new Authenticator() {
override def getPasswordAuthentication(): PasswordAuthentication = {
new PasswordAuthentication( s"$username", s"$password".toCharArray())
}
})
So as you can see I removed the header from the original request object and instead overrode the credentials. Make sure you do this before you call on the response object.

Scalatra - how do we do an internal redirect / forward of request

I want to call another internal url from my scalatra 'controller'. I can't do a simple redirect, as there's some security settings that mean a user has access only to the first url.
Is there a way to do this?
get("/foo") {
servletContext.getRequestDispatcher("/bar").forward(request, response)
}
The get() method is defined as (similar to POST, et al):
def get(transformers : org.scalatra.RouteTransformer*)(action : => scala.Any) : org.scalatra.Route
Depends on what you mean by internal redirect, I presume you just want to execute another route's action. You have a few options of what you can do. This seems to be working for me:
val canonicalEndpoint = get("/first/route") {
//do things in here
}
Then you could subsequently do:
get("/second/route")( canonicalEndpoint.action )
And I think you would get your desired response.
I like saving the whole Route response of the get() as you may also want to use that with scalatra's url() function in routing.