What are the causes for the the error NetworkError: 405 Method Not Allowed
I was using a web service and all of a sudden it started returning that error. its not maintained so it will not get fixed. I am curious if i can do something about this.
The offending web service url is: http://jsonpdb.appspot.com/add
The method (GET/POST/HEAD etc) you're trying to use on that URL is not supported by the app. Are you sure the API expects you to use the method you're using on that URL?
Most common cause is using the wrong 'get' vs 'post' for the response. Verify what's being sent and that the correct method appears in the your handler.
class MainHander(webapp.RequestHandler):
def get(self):
...
def post(self):
....
def delete(self):
....
Another common issue is having the main dispatch section parse urls, but then not supply them in the get/post/delete
def main():
application = webapp.WSGIApplication(
[ (r'/upload/([^/]+)?/?', UploadFileHandler),
The regex there has () in it... that's a parameter in the url path like: /upload/filename
class UploadFileHandler(webapp.RequestHandler):
def post(self, filename):
...
Supplying a link to code would be helpful.
I know this is an old thread but I did not find a satisfactory answer to the question for my own needs. Especially if you're handling an AJAX response, you may want to explicitly allow OPTIONS requests by checking for them in the dispatch of your custom WebApp2 handler:
class MyHandler(webapp2.RequestHandler):
def __init__(self, request, response):
self.initialize(request, response)
#The dispatch is overwritten so we can respond to OPTIONS
def dispatch(self):
self.response.headers.add_header("Access-Control-Allow-Origin", "*")
if self.request.method.upper() == 'OPTIONS':
self.response.status = 204
self.response.write('')
else:
super(MyHandler, self).dispatch();
Related
I am running a discord.py script that utilizes schedule.every(5).minutes.do() to run a function every 5 minutes. The function looks like:
async def send():
test = client.get_channel(1023183414628732998)
await test.send('test')
return 'sent'
and I am calling it like:
schedule.every(5).seconds.do(await send())
I am using seconds for testing purposes. The schedule code gets run when the bot comes online and is ready to send messages so it is not a problem with sending messages. I know this as it sends a message and then throws the error.
I have tried looking at multiple ways to fix it but none of them either make sense or do not work. I just want the bot to send a message/run a function every specified amount of time.
I'm not sure if schedule supports the use of coroutines. It's expecting to be given a function (callable) that can be run. await send() will actually just run the function so is returning a string. But send() will return the coroutine and not sure if schedule supports that. I couldn't find anything in the docs suggesting it does.
However, have you heard about tasks?
The first example in the docs:
from discord.ext import tasks, commands
class MyRepeatingTask(commands.Cog):
def __init__(self, client):
self.client = client
self.send.start()
def cog_unload(self):
self.send.cancel()
#tasks.loop(seconds=5.0)
async def send(self):
channel = self.client.get_channel(1023183414628732998)
await channel.send("test")
#send.before_loop
async def before_send(self):
await self.client.wait_until_ready()
There are simpler ways of creating tasks in the docs as well. Tasks are designed to be able to run functions at intervals or set dates/times so they'd probably be better suited for what you're trying to do.
We have a large flask_restplus application that's been in service for a year or so. We now would like to use flask_swagger_ui to work within this application to serve some statically generated swagger docs for part of the application.
Our flask_restplus-based application is already using namespaces, but the flask_swagger_ui docs that I have found seem to suggest that we have to use blueprints via its get_swaggerui_blueprint method in order to serve this swagger. However, when we do this, the flask_restplus application doesn't recognize the URL associated with this blueprint. We're wondering if perhaps this might be due to some sort of unwanted interaction between namespaces and blueprints within the same application ... or perhaps could it just be due to the fact that we're doing something incorrectly ... ???
Here is what I believe is the pertinent fragment of our code ...
app = flask.Flask(__name__)
api = flask_restplus.Api(
app,
version='1.0',
title='Test Application',
description='Test Application',
doc='/docs/'
)
ns = api.namespace('server', description='Main server', path='/server')
utilns = api.namespace('util', description='Util', path='/util')
SWAGGER_URL = '/swagger'
API_URL = 'http://petstore.swagger.io/v2/swagger.json' # just for testing
swaggerui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
'app_name': "Test application"
},
)
app.register_blueprint(swaggerui_blueprint)
# Set up endpoints under the namespaces defined above,
# and do some more initialization.
app.run()
However, if we try to access our app like this, http://our.domain.name:PORT/swagger/dist, it fails as follows ...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 FINAL//EN">
<title>405 Method Not Available</title>
<h1>Method Not Allowed</h1>
<p>This method is not allowed for the requested URL.</p>
We get the same error if we leave off "dist", as follows:
http://our.domain.name:PORT/swagger.
This also fails if we refer to a static swagger.json file instead of the petshop URL.
All the other namespace-defined endpoints work fine.
Can anyone see what we are doing incorrectly?
Thank you very much in advance.
I stumbled upon the solution. In flask_restplus, any blueprint and #app.route definitions must appear before the flask_restplus.Api instantiation. I couldn't find this in any documentation, and I got it from a discussion that involved someone who had encountered and finally fixed this issue. So, this is indeed a weird and seemingly undocumented interaction between blueprints and namespaces in flask_restplus.
Also, I discovered that url_prefix=SWAGGER_URL needs to be passed to app.register_blueprint along with the blueprint variable, itself.
Once I started doing the following, my swagger queries began to work:
app = flask.Flask(__name__)
# Any #app.route and blueprint definitions must
# appear before the flask_restplus.Api
# instantiation.
SWAGGER_URL = '/swagger'
# Use the following API_URL just for testing ...
API_URL = 'http://petstore.swagger.io/v2/swagger.json'
swaggerui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
'app_name': "Test application"
},
)
app.register_blueprint(
swaggerui_blueprint,
url_prefix=SWAGGER_URL
)
# OK. Now we can instantiate flask_restplus.API
api = flask_restplus.Api(
app,
version='1.0',
title='Test Application',
description='Test Application',
doc='/docs/'
)
ns = api.namespace(
'server',
description='Main server',
path='/server'
)
utilns = api.namespace(
'util',
description='Util',
path='/util'
)
# Set up endpoints under the namespaces defined above,
# and do some more initialization. And then ...
app.run()
I am having a trouble adding a "login with Facebook" feature to my Flask application which already using Flask-Security for the User authentication. What I really want is a Facebook button besides the login form, so that one can use Facebook instead of mail/password.
I have tried to do this with Facebook-social but failed, I don't really understand the docs. It seems to me that the user would have to be registered before connecting the account to Facebook, which is not the way I want it.
Is there anyone out there who have accomplished this? It seems to me that this would be a common case, but I can't find anything useful about it when googling.
I've done something similar, though with our own SSO instead of Facebook, but the principles are the same. In our case, we're using CAS, so #login_required redirects to our CAS login. On successful login, I use the CAS username attribute to dynamically add the user, then login via Flask-Security. Note that my example makes assumptions about your setup based on https://pythonhosted.org/Flask-Security/quickstart.html
def add_user(username):
if not user_datastore.find_user(username=username):
user_datastore.create_user(**get_user_data(username))
user_datastore.commit()
db.session.commit()
def get_user_data(username):
<Return dict mapping Facebook data to your user model>
def set_current_login(username):
try:
add_user(username)
security.current_user = user_datastore.find_user(username=username)
except Exception as e:
print str(e)
return False
return True
#app.route('/')
#login_required
def index():
set_current_login(<facebook username var>)
Note that you can also use the flask_security.utils.login_user() routine instead of setting the current_user object, which will also set a Flask-Security session cookie.
See the API documentation at https://pythonhosted.org/Flask-Security/api.html
Some of requests to my Web Application return data not in HTML format (JSON).
How to handle this correctly?
I wrote the following page definition:
import com.fasterxml.jackson.databind.ObjectMapper
import geb.Page
class JsonResponse extends Page {
static url = null;
static at = {
true;
}
static ObjectMapper mapper = new ObjectMapper();
static content = {
readTree {
def jsonString = $("pre").text();
mapper.readTree(jsonString)
}
}
}
and it apparently works. But the question is, how correct it is?
It takes data from inside pre tag. This is because I saw this content inside driver.pageSource. Is this correct? May be it is driver-dependent?
I put null into url, since the page has different url depending on query. Is this correct?
Geb is not intended to be used to interact with HTTP API endpoints because it is built on top of WebDriver and hence expects to be used via a browser and on HTML pages.
If you want to test HTTP API endpoints then I would suggest using an http client to back your tests. There are many of them out in the wild, just to name a few in no particular order:
Apache HttpClient
RestAssured - this one is specifically for testing
Ratpack's TestHttpClient - again intended to be used for testing
OkHttp
Unirest
I was able to download the content of a PDF in a geb unit test using the Direct Download API. It is handy because it takes all the cookies from the session but does the download separately from the browser.
Example from that documentation:
Browser.drive {
go "http://myapp.com/login"
// login
username = "me"
password = "secret"
login().click()
// now find the pdf download link
def downloadLink = $("a.pdf-download-link")
// now get the pdf bytes
def bytes = downloadBytes(downloadLink.#href)
}
There are different methods for downloading different kinds of data. See the DownloadSupport API docs.
Because geb uses HttpsURLConnection to connect to an https endpoint instead of using the browser you can have problems with self-signed certificates. I solved that using this Stack Overflow answer.
I agree that Geb is not intended to be used to interact with HTTP API endpoints, but there are some contexts where this can be helpful, so add this snippet here for posterity:
when: 'I retrieve the JSON transaction list'
go '/transaction/transactionList'
then: 'Valid data is retrieved'
JsonSlurper jsonSlurper = new JsonSlurper()
Map<String, List> transactionList = jsonSlurper.parseText(driver.pageSource)
assert transactionList.categories.class == ArrayList
This tutorial, React + Flux Backed by Rails API, by Fancy Pixel, says:
Now we need to change the application controller so that it inherits
from ActionController::API, and kiss the protect_from_forgery goodbye.
Since we are serving only JSON, it makes sense to add
respond_to :json
to the applciation controller, helps DRYing all out. While we are at
it, we might as well delete the assets and views folders, we won’t
need them.
I am not sure about what I am supposed to do.
This is what my application controller looks like:
class ApplicationController < ActionController::API
respond_to :json
end
Is it correct?
Also, should I keep or remove protect_from_forgery with: :null_session :
class ApplicationController < ActionController::API
protect_from_forgery with: :null_session
respond_to :json
end
To communicate from any Rails Backend (not even necessarily just an API) all you have to do is write the following in your API's controller(s):
class Api::V1::SearchController < ApplicationController
#Run an Authentication Method on their API Key
before_action :authenticate
def search
#Performs your backend logic
content_array = get_content_method
render :json => content_array
#Renders up a JSON that you can retrieve with an HTTP get request
end
end
Also on the topic of serving data, you can send your params in an obscured JSON, allowing you to hide your API Key, thus protecting you from unwanted access. My favorite way of doing this is by using the .to_query method to send over the necessary params. I have done it like so:
BASE_URL = "http://yourwebsite.com/search?"
def generate_search_url(params)
BASE_URL + params.to_query + "&Api-Key=#{ENV['API-KEY']}"
end
This way you can work with the data you're given just like any other params, but it would be more difficult to abuse the API without a granted key.