Error 405 Method not allowed - google-app-engine

I am desgining a web app using google app engine and python and
While extracting the form data ie. parameter values using the get request the following error occurs during the runtime:
405 Method Not Allowed
The method GET is not allowed for this resource.
Following is the code:
is the get mothos creating problem or is there any other solution to get parameter values.
class PostBody(webapp2.RequestHandler):
def post(self):
stringContent=cgi.escape(self.request.get('txtLocation'))
stringurl='http://maps.googleapis.com/maps/api/place/textsearch/json?query='|stringContent|'&sensor=false&key=mykey'
result=json.load(urllib.urlopen(stringurl))
self.response.write(result)
Thanks...

Try replacing
def post(self)
by
def get(self)

Related

Google AppEngine application log assigned to the wrong request log

When I look at the logs in the Google Log Viewer for my GAE project, I see that often the logs that I write myself in the code are assigned to the wrong request. Most of the time the log is assigned to the request directly after the request that produced the log entry.
As the root of every application log in GAE must be a request, this means that the wrong request is sometimes marked as error, because another request before produced an error, but the log is somehow assigned to the request after that.
I don't really do anything special, I use Ktor as my servlet and have an interceptor that creates a log when an exception occurs before returning status 500.
I use Java logging via SLF4J with the google cloud logging handler, but before that I used logback via SLf4J and had the same problem.
The content of the logs itself is also correct, the returned status of the request, the level of the log entry, the message, everything is ok.
I thought that it may be because I use kotlin and switch coroutine contexts during a single request, but in some cases the point where I write the log and where I send the response are exactly next to each other, so I'm not sure if kotlin has anything to do with it.
My logging.properties:
# To use this configuration, add to system properties : -Djava.util.logging.config.file="/path/to/file"
#
.level = INFO
# it is recommended that io.grpc and sun.net logging level is kept at INFO level,
# as both these packages are used by Stackdriver internals and can result in verbose / initialization problems.
io.grpc.netty.level=INFO
sun.net.level=INFO
handlers=com.google.cloud.logging.LoggingHandler
# default : java.log
com.google.cloud.logging.LoggingHandler.log=custom_log
# default : INFO
com.google.cloud.logging.LoggingHandler.level=INFO
# default : ERROR
com.google.cloud.logging.LoggingHandler.flushLevel=WARNING
# default : auto-detected, fallback "global"
#com.google.cloud.logging.LoggingHandler.resourceType=container
# custom formatter
com.google.cloud.logging.LoggingHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %2$s %5$s%6$s%n
#optional enhancers (to add additional fields, labels)
#com.google.cloud.logging.LoggingHandler.enhancers=com.example.logging.jul.enhancers.ExampleEnhancer
My logging relevant dependencies:
implementation "org.slf4j:slf4j-jdk14:1.7.30"
implementation "com.google.cloud:google-cloud-logging:1.100.0"
An example logging call:
exception<Throwable> { e ->
logger().error("Error", e)
call.respondText(e.message ?: "", ContentType.Text.Plain, HttpStatusCode.InternalServerError)
}
with logger() being:
import org.slf4j.Logger
import org.slf4j.LoggerFactory
inline fun <reified T : Any> T.logger(): Logger = LoggerFactory.getLogger(T::class.java)
Edit:
An example of the log in Google cloud. The first request has the query parameter GAID=cdda802e-fb9c-47ad-0794d394c913, but as you can see the error log for that request is in the one below, marked in red.

How to access Google Cloud Endpoints request header in Python and Java

In the endpoints method, how to access request header information?
Python:
In the endpoint method, self.request_state.headers provides this information.
E.g., self.request_state.headers.get('authorization')
Java:
Add an HttpServletRequest (req) parameter to your endpoint method. The headers are accessible through the method getHeader()
e.g., req.getHeader("Authorization")
See this question
What is working for me in python is the following:
The request I use: http://localhost:8080/api/hello/v1/header?message=Hello World!
python code:
#endpoints.api(name='hello', version='v1', base_path='/api/')
class EchoApi(remote.Service):
#endpoints.method(
# This method takes a ResourceContainer defined above.
message_types.VoidMessage,
# This method returns an Echo message.
EchoResponse,
path='header',
http_method='GET',
name='header')
def header(self, request):
header = request._Message__unrecognized_fields
output_message = header.get(u'message', None)[0]
return EchoResponse(message=output_message)

Difference between "drive.metadata.readonly" and "drive.readonly.metadata"

I want to ask what is the difference between DriveScopes.DRIVE_METADATA_READONLY and https://www.googleapis.com/auth/drive.readonly.metadata? In other words, what is the difference between
these two forms:
https://www.googleapis.com/auth/drive.metadata.readonly //DriveScopes.DRIVE_METADATA_READONLY
https://www.googleapis.com/auth/drive.readonly.metadata
When I was using service account for working with Drive API it takes me a long time to figure out, why my app was throwing unauthorized exception:
Uncaught exception from servlet
com.google.api.client.auth.oauth2.TokenResponseException: 403
{
"error" : "access_denied",
"error_description" : "Requested client not authorized."
}
The String constant DriveScopes.DRIVE_METADATA_READONLY was causing the exception. In which context should I use this constant?
That's clearly a mistake in the Java API client.
The API documentation states that the correct scope is :
https://www.googleapis.com/auth/drive.readonly.metadata
Whereas when you look at the latest javadoc (at the time of this answer), you get :
https://www.googleapis.com/auth/drive.metadata.readonly
You should ignore the DriveScopes constant and create your own constant, while the Google Drive team fixes this.

No api proxy found for service "memcache" GAE unittest2

I'am trying to write tests to my app. I make a simple test case:
def test_put(self):
Result(
id="23738",
target_id="23738",
).put()
and after running, it raises an error:
AssertionError: No api proxy found for service "memcache"
I don't know, how to fix it.
And this is my set_up:
def set_up(self):
self.testbed = testbed.Testbed()
self.testbed.activate()
self.testbed.init_datastore_v3_stub()
self.testbed.init_memcache_stub()
self.testbed.init_user_stub()
and tear_down:
def tear_down(self):
self.testbed.deactivate()
The function names in your code are:
def set_up(self):
...
def tear_down(self):
...
However, according to the Python unittest documentation, the proper names are setUp and tearDown (note the lack of underscore and camelCase).
You can see similar uses of the functions in the AppEngine Python local unit testing documentation.

flask: error_handler for blueprints

Can error_handler be set for a blueprint?
#blueprint.errorhandler(404)
def page_not_found(error):
return 'This page does not exist', 404
edit:
https://github.com/mitsuhiko/flask/blob/18413ed1bf08261acf6d40f8ba65a98ae586bb29/flask/blueprints.py
you can specify an app wide and a blueprint local error_handler
You can use Blueprint.app_errorhandler method like this:
bp = Blueprint('errors', __name__)
#bp.app_errorhandler(404)
def handle_404(err):
return render_template('404.html'), 404
#bp.app_errorhandler(500)
def handle_500(err):
return render_template('500.html'), 500
errorhandler is a method inherited from Flask, not Blueprint.
If you are using Blueprint, the equivalent is app_errorhandler.
The documentation suggests the following approach:
def app_errorhandler(self, code):
"""Like :meth:`Flask.errorhandler` but for a blueprint. This
handler is used for all requests, even if outside of the blueprint.
"""
Therefore, this should work:
from flask import Blueprint, render_template
USER = Blueprint('user', __name__)
#USER.app_errorhandler(404)
def page_not_found(e):
""" Return error 404 """
return render_template('404.html'), 404
On the other hand, while the approach below did not raise any error for me, it didn't work:
from flask import Blueprint, render_template
USER = Blueprint('user', __name__)
#USER.errorhandler(404)
def page_not_found(e):
""" Return error 404 """
return render_template('404.html'), 404
add error handling at application level using the request proxy object:
from flask import request,jsonify
#app.errorhandler(404)
#app.errorhandler(405)
def _handle_api_error(ex):
if request.path.startswith('/api/'):
return jsonify(ex)
else:
return ex
flask Documentation
I too couldn't get the top rated answer to work, but here's a workaround.
You can use a catch-all at the end of your Blueprint, not sure how robust/recommended it is, but it does work. You could also add different error messages for different methods too.
#blueprint.route('/<path:path>')
def page_not_found(path):
return "Custom failure message"
Surprised others didn't mention miguelgrinberg's excellent tutorial.
https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-vii-error-handling
I found the sentry framework for error handling (links below). Seems overly complex. not sure of the threshold where it becomes useful.
https://flask.palletsprojects.com/en/1.1.x/errorhandling/
https://docs.sentry.io/platforms/python/guides/flask/
I combined previous excellent answers with the official docs from Flask, section 'Returning API Errors as JSON', in order to provide a more general approach.
Here is a working PoC that you can copy and paste on your registered blueprint API route handler (e.g. app/api/routes.py):
#blueprint.app_errorhandler(HTTPException)
def handle_exception(e):
"""Return JSON instead of HTML for HTTP errors."""
# start with the correct headers and status code from the error
response = e.get_response()
# replace the body with JSON
response.data = json.dumps({
"code": e.code,
"name": e.name,
"description": e.description,
})
response.content_type = "application/json"
return response
Flask doesnt support blueprint level error handlers for 404 and 500 errors. A BluePrint is a leaky abstraction. Its better to use a new WSGI App for this, if you need separate error handlers, this makes more sense.
Also i would recommend not to use flask, it uses globals all over the places, which makes your code difficult to manage if it grows bigger.

Resources