HTTP Deadline exceeded waiting for python Google Cloud Endpoints on python client localhost - python-2.7

I want to build a python client to talk to my python Google Cloud Endpoints API. My simple HelloWorld example is suffering from an HTTPException in the python client and I can't figure out why.
I've setup simple examples as suggested in this extremely helpful thread. The GAE Endpoints API is running on localhost:8080 with no problems - I can successfully access it in the API Explorer. Before I added the offending service = build() line, my simple client ran fine on localhost:8080.
When trying to get the client to talk to the endpoints API, I get the following error:
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/dist27/gae_override/httplib.py", line 526, in getresponse
raise HTTPException(str(e))
HTTPException: Deadline exceeded while waiting for HTTP response from URL: http://localhost:8080/_ah/api/discovery/v1/apis/helloworldendpoints/v1/rest?userIp=%3A%3A1
I've tried extending the http deadline. Not only did that not help, but such a simple first call on localhost should not be exceeding a default 5s deadline. I've also tried accessing the discovery URL directly within a browser and that works fine, too.
Here is my simple code. First the client, main.py:
import webapp2
import os
import httplib2
from apiclient.discovery import build
http = httplib2.Http()
# HTTPException happens on the following line:
# Note that I am using http, not https
service = build("helloworldendpoints", "v1", http=http,
discoveryServiceUrl=("http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest"))
# result = service.resource().method([parameters]).execute()
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-type'] = 'text/plain'
self.response.out.write("Hey, this is working!")
app = webapp2.WSGIApplication(
[('/', MainPage)],
debug=True)
Here's the Hello World endpoint, helloworld.py:
"""Hello World API implemented using Google Cloud Endpoints.
Contains declarations of endpoint, endpoint methods,
as well as the ProtoRPC message class and container required
for endpoint method definition.
"""
import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote
# If the request contains path or querystring arguments,
# you cannot use a simple Message class.
# Instead, you must use a ResourceContainer class
REQUEST_CONTAINER = endpoints.ResourceContainer(
message_types.VoidMessage,
name=messages.StringField(1),
)
package = 'Hello'
class Hello(messages.Message):
"""String that stores a message."""
greeting = messages.StringField(1)
#endpoints.api(name='helloworldendpoints', version='v1')
class HelloWorldApi(remote.Service):
"""Helloworld API v1."""
#endpoints.method(message_types.VoidMessage, Hello,
path = "sayHello", http_method='GET', name = "sayHello")
def say_hello(self, request):
return Hello(greeting="Hello World")
#endpoints.method(REQUEST_CONTAINER, Hello,
path = "sayHelloByName", http_method='GET', name = "sayHelloByName")
def say_hello_by_name(self, request):
greet = "Hello {}".format(request.name)
return Hello(greeting=greet)
api = endpoints.api_server([HelloWorldApi])
Finally, here is my app.yaml file:
application: <<my web client id removed for stack overflow>>
version: 1
runtime: python27
api_version: 1
threadsafe: yes
handlers:
- url: /_ah/spi/.*
script: helloworld.api
secure: always
# catchall - must come last!
- url: /.*
script: main.app
secure: always
libraries:
- name: endpoints
version: latest
- name: webapp2
version: latest
Why am I getting an HTTP Deadline Exceeded and how to I fix it?

On your main.py you forgot to add some variables to your discovery service url string, or you just copied the code here without it. By the looks of it you were probably suppose to use the format string method.
"http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest".format(api='helloworldendpoints', apiVersion="v1")
By looking at the logs you'll probably see something like this:
INFO 2015-11-19 18:44:51,562 module.py:794] default: "GET /HTTP/1.1" 500 -
INFO 2015-11-19 18:44:51,595 module.py:794] default: "POST /_ah/spi/BackendService.getApiConfigs HTTP/1.1" 200 3109
INFO 2015-11-19 18:44:52,110 module.py:794] default: "GET /_ah/api/discovery/v1/apis/helloworldendpoints/v1/rest?userIp=127.0.0.1 HTTP/1.1" 200 3719
It's timing out first and then "working".
Move the service discovery request inside the request handler:
class MainPage(webapp2.RequestHandler):
def get(self):
service = build("helloworldendpoints", "v1",
http=http,
discoveryServiceUrl=("http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest")
.format(api='helloworldendpoints', apiVersion='v1'))

Related

Flask: Unknown error although 200 response code is returned

I have created a simple Flask RESTful API with a single function used to service GET requests and which expects several URL parameters:
import logging
from flask import Flask
from flask_restful import Api, Resource
from webargs import fields
from webargs.flaskparser import abort, parser, use_args
# initialize the Flask application and API
app = Flask(__name__)
api = Api(app)
# ------------------------------------------------------------------------------
# set up a basic, global logger object which will write to the console
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")
_logger = logging.getLogger(__name__)
# ------------------------------------------------------------------------------
class Abc(Resource):
abc_args = {"rtsp": fields.Url(required=True),
"start": fields.Integer(required=True),
"duration": fields.Integer(required=True),
"bucket": fields.String(required=True),
"prefix": fields.String(missing="")}
#use_args(abc_args)
def get(self, args) -> (str, int):
_logger.info("Recording video clip with the following parameters:\n"
f"\tRTSP URL: {args['rtsp']}"
f"\tStart seconds: {args['start']}"
f"\tDuration seconds: {args['duration']}"
f"\tS3 bucket: {args['bucket']}"
f"\tS3 key prefix: {args['prefix']}")
return "OK", 200
# ------------------------------------------------------------------------------
# This error handler is necessary for usage with Flask-RESTful
#parser.error_handler
def handle_request_parsing_error(err, req, schema, error_status_code, error_headers):
"""
webargs error handler that uses Flask-RESTful's abort function to return
a JSON error response to the client.
"""
abort(error_status_code, errors=err.messages)
# ------------------------------------------------------------------------------
if __name__ == '__main__':
api.add_resource(Abc, "/abc", endpoint="abc")
app.run(debug=True)
When I send a GET request to the endpoint with or without parameters I get none of the expected behavior -- if good parameters are included in the GET request then I expect to see a log message in the console, and if none of the required parameters are present then I expect to get some sort of error as a result. Instead, I get what appear to be 200 response codes in the console and simply the phrase "Unknown Error" in the main browser window.
For example, if I enter the following URL without the expected parameters into my Chrome browser's address bar: http://127.0.0.1:5000/abc
I then see this in the console:
2019-05-28 17:42:14 INFO 127.0.0.1 - - [28/May/2019 17:42:14] "GET /abc HTTP/1.1" 200 -
My assumption is that the above should throw an error of some sort indicating the missing URL parameters.
If I enter the following URL with the expected parameters into my Chrome browser's address bar: http://127.0.0.1:5000/abc?rtsp=rtsp://user:passwd#171.25.14.15:554&start=1559076593&duration=10&bucket=testbucket&prefix=test.
I then see this in the console:
2019-05-28 17:45:31 INFO 127.0.0.1 - - [28/May/2019 17:45:31] "GET /abc?rtsp=rtsp://user:passwd#171.25.14.15:554&start=1559076593&duration=10&bucket=testbucket&prefix=test. HTTP/1.1" 200 -
My assumption is that the above should cause the logger to print the information message to the console as is defined in the Abc.get function.
If I use curl at the command line then I get the following result:
$ curl "http://127.0.0.1:5000/abc?rtsp=rtsp://user:passwd#171.25.14.15:554&start=1559076593&duration=10&bucket=testbucket&prefix=test."
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>None Unknown Error</title>
<h1>Unknown Error</h1>
<p></p>
Whi is this going amiss, and how I can achieve the expected behavior? (My intention is to use this approach to pass arguments to a more realistic GET handler that will launch a video recording function when the request is received, the above has been simplified as much as possible for clarity.)
I am using Flask 1.0.3, Flask-Restful 0.3.6, and Webargs 5.3.1 in an Anaconda environment (Python 3.7) on Ubuntu 18.04.
I have managed to get the expected behavior using a simpler code that does not rely upon flask_restful. See below:
import logging
from flask import Flask, request
# initialize the Flask application
app = Flask(__name__)
# ------------------------------------------------------------------------------
# set up a basic, global logger object which will write to the console
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")
_logger = logging.getLogger(__name__)
# ------------------------------------------------------------------------------
#app.route('/clip', methods=['GET'])
def record_and_store_clip():
message = "Recording video clip with the following parameters:\n" + \
f"\tRTSP URL: {request.args.get('rtsp')}\n" + \
f"\tStart seconds: {request.args.get('start')}\n" + \
f"\tDuration seconds: {request.args.get('duration')}\n" + \
f"\tS3 bucket: {request.args.get('bucket')}\n" + \
f"\tS3 key prefix: {request.args.get('prefix')}\n"
_logger.info(message)
return message
# ------------------------------------------------------------------------------
if __name__ == '__main__':
app.run(debug=True)

Problems with flask and bad request

I was programming myself a pretty nice api to get some json data from my gameserver to my webspace using json,
but everytime i am sending a request using angular i am getting this:
127.0.0.1 - - [20/Mar/2018 17:07:33] code 400, message Bad request version
("▒\x9c▒▒{▒'\x12\x99▒▒▒\xadH\x00\x00\x14▒+▒/▒,▒0▒\x13▒\x14\x00/\x005\x00")
127.0.0.1 - - [20/Mar/2018 17:07:33] "▒\x9dtTc▒\x93▒4▒M▒▒▒▒▒\x9c▒▒{▒'\x99▒▒▒▒H▒+▒/▒,▒0▒▒/5"
HTTPStatus.BAD_REQUEST -
127.0.0.1 - - [20/Mar/2018 17:07:33] code 400, message Bad request syntax
('\x16\x03\x01\x00▒\x01\x00\x00\x9d\x03\x03▒k,&▒▒ua\x8c\x82\x17\x05▒QwQ$▒0▒▒\x9f▒B1\x98\x19W▒▒▒▒\x00\x00\x14▒+▒/▒,▒0▒\x13▒\x14\x00/\x005\x00')
127.0.0.1 - - [20/Mar/2018 17:07:33] "▒\x9d▒k,&▒▒ua\x8c\x82▒QwQ$▒0▒▒\x9f▒B1\x98W▒▒▒▒▒+▒/▒,▒0▒▒/5"
HTTPStatus.BAD_REQUEST -
127.0.0.1 - - [20/Mar/2018 17:07:33] code 400, message Bad request syntax
('\x16\x03\x01\x00▒\x01\x00\x00▒\x03\x03)▒▒\x1e\xa0▒\t\r\x14g%▒▒\x17▒▒\x80\x8d}▒F▒▒\x08U▒ġ▒▒\x06▒\x00\x00\x1c▒+▒/▒,▒0▒')
g%▒▒▒▒\x80\x8d}▒F▒U▒ġ▒▒▒▒+▒/▒,▒0▒" HTTPStatus.BAD_REQUEST -
My api
from flask import Flask, jsonify
from flaskext.mysql import MySQL
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
cors = CORS(app, resources={r"/punishments": {"origins": "http://localhost:5000" "*"}})
mysql = MySQL()
# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'test'
app.config['MYSQL_DATABASE_PASSWORD'] = 'Biologie1'
app.config['MYSQL_DATABASE_DB'] = 'test'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)
#app.route('/punishments', methods=['GET'])
#cross_origin(origin='localhost:5000',headers=['Content- Type','Authorization'])
def get():
cur = mysql.connect().cursor()
cur.execute('''select * from test.punishments''')
r = [dict((cur.description[i][0], value)
for i, value in enumerate(row)) for row in cur.fetchall()]
return jsonify({'punishments' : r})
if __name__ == '__main__':
app.run()
My client function
export class ApiUserService {
private _postsURL = "https://localhost:5000/punishments";
constructor(private http: HttpClient) {
}
getPosts(): Observable<Punishments[]> {
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/json; charset=utf-8');
return this.http
.get(this._postsURL,{
headers: {'Content-Type':'application/json; charset=utf-8'}
})
.map((response: Response) => {
return <Punishments[]>response.json();
})
.catch(this.handleError);
}
private handleError(error: Response) {
return Observable.throw(error.statusText);
}
}
I had the same error as yours.
My flask server was installed inside respberry-pi and I was trying to access it using https://ip:5000.
The problem was I was using https instead of http.
When I changed it to http://ip:5000, it worked.
I also faced same problem
use only http not https :-
http://ip:portnumber
Recently I also faced this, the problem came from the SSL config on my app.
In my .env I set the SSL_DISABLE to False, then I change it to True.
change SSL_DISABLE=False to SSL_DISABLE=True
So, the point here is are: check your URL, maybe be it something like: https://127.0.0.1:5000, just change it to http://127.0.0.1:5000.
Hope it helps to someone who also facing this issue in the future.
in my case, i was trying to debug SocketIo server running on flask. I was trying to access the server using wss:// which was causing the bad request. Changing it to ws:// resolved the issue.
In my case i resolve the problem reverting flask version to Flask==1.1.4 and jinja dependency to Jinja2==3.0.3

running cron in google app engine gives 404 error

My cronjob does not run when I click Run Now in http://localhost:8000/cron
My app contains the following files
hello.py
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers["Content-Type"] = "text/plain"\
self.response.write("Congratulations, it's a web app!")
routes = [('/', MainPage)]
my_app = webapp2.WSGIApplication(routes, debug=True)
app.yaml
application: hello
version: 1
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /.*
script: hello.my_app
- url: /tasks/summary
script: hello.application
cron_script.py
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class CronTask(webapp.RequestHandler):
def get(self):
f = open("test.txt","w") #opens file with name of "test.txt"
f.write("I am a test file.")
f.write("Maybe someday, he will promote me to a real file.")
f.write("Man, I long to be a real file")
f.write("and hang out with all my new real file friends.")
f.close()
application = webapp.WSGIApplication([('/tasks/summary', CronTask)],
debug=True)
if __name__ == '__main__':
run_wsgi_app(application)
cron.yaml
cron:
- description: daily summary job
url: /tasks/summary
target: beta
schedule: every 1 minutes
Your cron.yaml file will make requests to /tasks/summary.
Your app.yaml directs them to your hello.application.
But your matching hello.py file doesn't have a matching route for /tasks/summary.
You could expand your existing route pattern to match that path:
routes = [('/.*', MainPage)]
But more likely you'll add specific route for it (and you'll need to add the matching handler code for it as well):
routes = [('/tasks/summary', CronHandler)]

The app returned an error when the Google Cloud Endpoints server attempted to communicate with it

Hi I'm new to Google App Engine and Cloud Endpoints.
I have an app engine that serves web application.
And I want to use it with Cloud Endpoints.
So I just added source codes from here:
https://cloud.google.com/appengine/docs/python/endpoints/getstarted/backend/write_api
But I cannot deploy app and get this error message:
Checking if Endpoints configuration has been updated.
07:13 AM Failed to update Endpoints configuration. The app returned an error when the Google Cloud Endpoints server attempted to communicate with it.
07:13 AM See the deployment troubleshooting documentation for more information: https://developers.google.com/appengine/docs/python/endpoints/test_deploy#troubleshooting_a_deployment_failure
And this is my source codes
import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote
package = 'Hello'
class Greeting(messages.Message):
"""Greeting that stores a message."""
message = messages.StringField(1)
class GreetingCollection(messages.Message):
"""Collection of Greetings."""
items = messages.MessageField(Greeting, 1, repeated=True)
STORED_GREETINGS = GreetingCollection(items=[
Greeting(message='hello world!'),
Greeting(message='goodbye world!'),
])
#endpoints.api(name='helloworld', version='v1')
class HelloWorldApi(remote.Service):
"""Helloworld API v1."""
#endpoints.method(message_types.VoidMessage, GreetingCollection,
path='hellogreeting', http_method='GET',
name='greetings.listGreeting')
def greetings_list(self, unused_request):
return STORED_GREETINGS
ID_RESOURCE = endpoints.ResourceContainer(
message_types.VoidMessage,
id=messages.IntegerField(1, variant=messages.Variant.INT32))
#endpoints.method(ID_RESOURCE, Greeting,
path='hellogreeting/{id}', http_method='GET',
name='greetings.getGreeting')
def greeting_get(self, request):
try:
return STORED_GREETINGS.items[request.id]
except (IndexError, TypeError):
raise endpoints.NotFoundException('Greeting %s not found.' %
(request.id,))
APPLICATION = endpoints.api_server([HelloWorldApi])
exactly same with tutorial
and my app.yaml
application: my application id
version: application version
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /data
script: MLP.app
login: admin
- url: /insert_db
script: MLP.app
login: admin
- url: /validete
script: MLP.app
login: admin
- url: /stylesheets
static_dir: stylesheets
- url: /js
static_dir: js
- url: /.*
script: MLP.app
- url: /_ah/spi/.*
script: MLP_mobile_backend.APPLICATION
libraries:
- name: webapp2
version: latest
- name: jinja2
version: latest
- name: pycrypto
version: latest
- name: endpoints
version: 1.0
MLP.py is just web service with webapp2
How can I solve the problem?
From the app.yaml line script: MLP_mobile_backend.APPLICATION, it means your code sample must live in a MLP_mobile_backend.py file at the root of your app engine project
.
├── app.yaml
├── MLP.py
└── MLP_mobile_backend.py
with an endpoint api server named APPLICATION defined in that file just as in your code sample above.
APPLICATION = endpoints.api_server([HelloWorldApi])
After those requirements are fulfilled, this line points to how to access your endpoints:
#endpoints.api(name='helloworld', version='v1')
So for example, let's say you're running your devserver's module on port 8080 and you want to access the hellogreeting path:
#endpoints.method(message_types.VoidMessage, GreetingCollection,
path='hellogreeting', http_method='GET',
name='greetings.listGreeting')
you can use cURL or httpie or your browser to locally navigate to the devserver's default module at http://localhost:8080/_ah/api/helloworld/v1/hellogreeting or with Google's API explorer at http://localhost:8080/_ah/api/explorer which should result in this response body:
{
"items": [
{
"message": "hello world!"
},
{
"message": "goodbye world!"
}
]
}
Once you get it set up locally, you can then deploy it.
More here

Python requests 503 erros when trying to access localhost:8000

I am facing a bit of a situation,
Scenario: I got a django rest api running on my localhost:8000 and I want to access the api using my command line. I have tried urllib2 and python requests libs to talk to the api but failed(i'm getting a 503 error). But when I pass google.com as the url, I am getting the expected response. So I believe my approach is correct but I'm doing something wrong. please see the code below :
import urllib, urllib2, httplib
url = 'http://localhost:8000'
httplib.HTTPConnection.debuglevel = 1
print "urllib"
data = urllib.urlopen(url);
print "urllib2"
request = urllib2.Request(url)
opener = urllib2.build_opener()
feeddata = opener.open(request).read()
print "End\n"
Envioroments:
OS Win7
python v2.7.5
Django==1.6
Markdown==2.3.1
colorconsole==0.6
django-filter==0.7
django-ping==0.2.0
djangorestframework==2.3.10
httplib2==0.8
ipython==1.0.0
jenkinsapi==0.2.14
names==0.3.0
phonenumbers==5.8b1
requests==2.1.0
simplejson==3.3.1
termcolor==1.1.0
virtualenv==1.10.1
Thanks
I had a similar problem, but found that it was the company's proxy that was preventing from pinging myself.
503 Reponse when trying to use python request on local website
Try:
>>> import requests
>>> session = requests.Session()
>>> session.trust_env = False
>>> r = session.get("http://localhost:5000/")
>>> r
<Response [200]>
>>> r.content
'Hello World!'
If you are registering your serializers with DefaultRouter then your api will appear at
http://localhost:8000/api/ for an html view of the index
http://localhost:8000/api/.json for a JSON view of the index
http://localhost:8000/api/appname for an html view of the individual resource
http://localhost:8000/api/appname/.json for a JSON view of the individual resource
you can check the response in your browser to make sure your URL is working as you expect.