问题
I added login: Admin to app.yaml like documentation is described, but I still have a 302 erro when runing a task with cron in google app engine.
I have this app.yaml
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
login: admin
And this cron.yaml
cron:
- description: "Dashboard"
url: /processdate?from=2016-03-01&until=2016-03-31
schedule: every day 23:46
timezone: Europe/Madrid
I obtain this error
0.1.0.1 - - [26/Oct/2018:00:49:40 +0200] "GET /processdate?from=2016-03-01&until=2016-03-31 HTTP/1.1" 302 355 - "AppEngine-Google; (+http://code.google.com/appengine)" "p20000.appspot.com" ms=74 cpu_ms=12 cpm_usd=3.9674e-8 loading_request=0 instance=00c61b117c78f767097d6896daa1f8967a815c14a94d54578ac19efa9d50a5077d5a app_engine_release=1.9.65 trace_id=3c92edad090b5a57d249bd92be246e58
httpRequest: {
status: 302
}
insertId: "5bd248840005a3aae7fa2111"
labels: {
clone_id: "00c61b117c78f767097d6896daa1f8967a815c14a94d54578ac19efa9d50a5077d5a"
}
logName: "projects/p201309/logs/appengine.googleapis.com%2Frequest_log"
operation: {
first: true
id: "5bd2488400ff047fe69ec5d94d0001657e62692d70682d3230313330390001323031383130323674303033383339000100"
last: true
producer: "appengine.googleapis.com/request_id"
}
protoPayload: {
@type: "type.googleapis.com/google.appengine.logging.v1.RequestLog"
appEngineRelease: "1.9.65"
appId: "e~myappname"
cost: 3.9674e-8
endTime: "2018-10-25T22:49:40.369327Z"
finished: true
first: true
host: "p200000.appspot.com"
httpVersion: "HTTP/1.1"
instanceId: "00c61b117c78f767097d6896daa1f8967a815c14a94d54578ac19efa9d50a5077d5a"
instanceIndex: -1
ip: "0.1.0.1"
latency: "0.074441s"
megaCycles: "12"
method: "GET"
requestId: "5bd2488400ff047fe69ec5d94d0001657e62692d70682d3230313330390001323031383130323674303033383339000100"
resource: "/processdate?from=2016-03-01&until=2016-03-31"
responseSize: "355"
startTime: "2018-10-25T22:49:40.294886Z"
status: 302
taskName: "25ed634cde05b07d9a7906f2161d2b16"
taskQueueName: "__cron"
traceId: "3c92edad090b5a57d249bd92be246e58"
traceSampled: true
urlMapEntry: "main.app"
userAgent: "AppEngine-Google; (+http://code.google.com/appengine)"
versionId: "20181026t003839"
}
receiveTimestamp: "2018-10-25T22:49:40.376251430Z"
resource: {
labels: {
module_id: "default"
project_id: "myappname"
version_id: "20181026t003839"
zone: "eu2"
}
type: "gae_app"
}
timestamp: "2018-10-25T22:49:40.294886Z"
trace: "projects/myappname/traces/3c92edad090b5a57d249bd92be246e58"
traceSampled: true
}
Any idea about what could be the problem or how to solve it?
I don't have any problem runing this script in my local machine.
------ UPDATED WITH A MUCH MORE SIMPLE APP ------
I tested something much more simple. This is working when I run https://myappname.appspot.com/hellocron and http://myappname.appspot.com/hellocron
With this the result it's what expected.
But when I run it with cron error 302 it's returned again
----------- app.yaml
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /hellocron
script: main.app
login: admin
secure: always
----------- cron.yaml
cron:
- description: "hellocron"
url: /hellocron
schedule: every day 23:46
timezone: Europe/Madrid
------------ I had the same error result
0.1.0.1 - - [01/Nov/2018:12:29:49 +0100] "GET /hellocron HTTP/1.1" 302 267 - "AppEngine-Google; (+http://code.google.com/appengine)" "myappname.appspot.com" ms=8 cpu_ms=9 cpm_usd=2.9839e-8 loading_request=0 instance=00c61b117cb863320ce80ff59a2b5b4b20ee440529428f43d612baa0e980733727302b27 app_engine_release=1.9.65 trace_id=9b9fa8ad127ad41f7907529c3863a0a9
{
httpRequest: {
status: 302
}
insertId: "5bdae3ad0004cfe52d64d457"
labels: {
clone_id: "00c61b117cb863320ce80ff59a2b5b4b20ee440529428f43d612baa0e980733727302b27"
}
logName: "projects/myappname/logs/appengine.googleapis.com%2Frequest_log"
operation: {
first: true
id: "5bdae3ad00ff04ac4decaecea60001657e62692d70682d3230313330390001323031383131303174313135363535000100"
last: true
producer: "appengine.googleapis.com/request_id"
}
protoPayload: {
@type: "type.googleapis.com/google.appengine.logging.v1.RequestLog"
appEngineRelease: "1.9.65"
appId: "e~myappname"
cost: 2.9839e-8
endTime: "2018-11-01T11:29:49.315161Z"
finished: true
first: true
host: "myappname.appspot.com"
httpVersion: "HTTP/1.1"
instanceId: "00c61b117cb863320ce80ff59a2b5b4b20ee440529428f43d612baa0e980733727302b27"
instanceIndex: -1
ip: "0.1.0.1"
latency: "0.008908s"
megaCycles: "9"
method: "GET"
requestId: "5bdae3ad00ff04ac4decaecea60001657e62692d70682d3230313330390001323031383131303174313135363535000100"
resource: "/hellocron"
responseSize: "267"
startTime: "2018-11-01T11:29:49.306253Z"
status: 302
taskName: "b0467e8a57f53a8ee2b827ca35db275f"
taskQueueName: "__cron"
traceId: "9b9fa8ad127ad41f7907529c3863a0a9"
traceSampled: true
urlMapEntry: "main.app"
userAgent: "AppEngine-Google; (+http://code.google.com/appengine)"
versionId: "20181101t115655"
}
receiveTimestamp: "2018-11-01T11:29:49.321937019Z"
resource: {
labels: {
module_id: "default"
project_id: "myappname"
version_id: "20181101t115655"
zone: "eu2"
}
type: "gae_app"
}
timestamp: "2018-11-01T11:29:49.306253Z"
trace: "projects/myappname/traces/9b9fa8ad127ad41f7907529c3863a0a9"
traceSampled: true
}
The code for /hellocron in python is this one basically:
decorator = OAuth2DecoratorFromClientSecrets(
os.path.join(os.path.dirname(__file__), 'client_secrets.json'),
scope='https://www.googleapis.com/auth/bigquery')
class hellocron (webapp2.RequestHandler):
@decorator.oauth_required
def get(self):
self.response.write('hellocron')
app = webapp2.WSGIApplication([
('/hellocron', hellocron),
(decorator.callback_path, decorator.callback_handler()) ], debug=True)
回答1:
You want to drop the @decorator.oauth_required from the cron url handler code.
The cron service does not have any user credentials (it doesn't run as a user) so that decorator will cause a re-direction to a login service - hence the 302 response. You should be able to verify this by re-trying your manual check but from an incognito browser window.
To secure the cron service URLs you can't use regular user authentication for this reason. But you can use login: admin in the app.yaml file and, if you want, also check for the X-Appengine-Cron: true header or the 0.1.0.1 source IP address, see Securing URLs for cron.
Similarly you might need to drop the secure: always from the respective app.yaml handler definition (I don't have it enabled for my app): I'm not sure if the cron service makes its GET request using http or https. If it makes it using http the secure: always config will also cause a redirection to a https URL. You can easily check if this is correct or not following my earlier comment after you drop the decorator.
回答2:
My name is Dan I'm from google cloud support.
As I could understand, you're receiving a 302 response when launching Cron jobs. Have you a custom domain with SSL enabled? I ask you this because we have received this report from some customers that are using HTTP instead of HTTPS. Are you running your application on App Engine flexible? This information will help me to better understand your current scenario.
I will be awaiting your reply.
回答3:
I wanted to post this solution as I was pulling my hair out yesterday trying to figure out why my GAE cron jobs kept failing and this thread helped me fine tune the solution that worked.
I am using Python, but the idea seems the same. In my cron script (i.e. the page visited with the cron logic), I had a redirect after successful execution of a report, due to this the cron would state it failed in GAE, but the logic would still execute correctly.
To fix the issue, all I did was return a simple HTTP response so the cron thought everything loaded correctly on the page instead of the redirect or not returning an HTTP response all together.
回答4:
I was trying to execute a django admin endpoint from gcloud app engine. It seems there is no way to make gcloud crons login with any credentials before running so here is what you have to do if you find yourself in this situation (receiving 302 in your crons executions):
- Make the url public, that means: no credentials needed to run it.
- Gcloud crons send request including X-AppEngine-Cron in it's headers. They strip 'X-' from all their headers so you may trust this particular one. All you have to do is check for this header in your endpoint request as this guy does.
Doc: https://cloud.google.com/appengine/docs/flexible/go/scheduling-jobs-with-cron-yaml?hl=es-419#validating_cron_requests
来源:https://stackoverflow.com/questions/52999203/error-302-running-cron-and-loginadmin-in-app-yaml-in-google-app-engine