How to do OAuth-requiring operations in a GAE cron

2020-03-22 10:48发布

问题:

This post is a followup to How to do OAuth-requiring operations in a GAE Task Queue?. As suggested by bossylobster in this post, I did try to hardcode the user_id in my script, but the cron task always fails:

  • I can see it being triggered in the logs...

    2013-05-31 14:20:00.879 /update 302 5ms 0kb AppEngine-Google; (+http://code.google.com/appengine)
    0.1.0.1 - - [31/May/2013:11:20:00 -0700] "GET /update HTTP/1.1" 302 385 - "AppEngine-Google; (+http://code.google.com/appengine)" "myapp.appspot.com" ms=6 cpu_ms=0 cpm_usd=0.000043 queue_name=__cron task_name=... app_engine_release=1.8.0 instance=...
    
  • ... however, it always fails (shows up as red "Failed" in AppEngine's Cron Jobs section), and the task queue it's supposed to run never pops up in the Task Queues section.

What I don't understand is that if I open /update manually I have the login prompt below. How is cron supposed to bypass that? How can I debug what's going on?

Thanks for the help.

EDIT/followup on @dlebech answer: The problem persists after adding a login: admin line to the concerned url in app.yaml. Locally (by signing in as an administrator and visiting the URL of the handler in your browser as mentioned by the Securing URLs for Cron) everything goes fine, but once I deploy, my app never gets past the OAuth2 decorator:

  • With a few debug print statements...

    import webapp2
    ...
    
    YOUTUBE_RW_SCOPE = "https://www.googleapis.com/auth/youtube"
    YOUTUBE_API_SERVICE_NAME = "youtube"
    YOUTUBE_API_VERSION = "v3"
    print "Building youtube object"
    print "Built youtube object"
    youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION)
    print "Building decorator object"
    decorator = OAuth2DecoratorFromClientSecrets(CLIENT_SECRETS, YOUTUBE_RW_SCOPE)
    print "Built decorator object"
    ...
    
    class FetchHandlerPage(webapp2.RequestHandler):
        print "Entering FetchHandlerPage"
    
        @decorator.oauth_required
        def get(self):
            print "Entering FetchHandlerPage:get"
            gae_user_id = USER_ID
            query_string = urlencode({'user_id': gae_user_id})
            taskqueue.add(url='/fetchworker?' + query_string, method='GET')
    
  • ... here is what I see after deployment in my GAE logs (the logs stops at the last line, nothing happens next):

    2013-05-31 16:12:02.765 /fetch 302 1746ms 0kb AppEngine-Google; (+http://code.google.com/appengine)
    0.1.0.1 - - [31/May/2013:13:12:02 -0700] "GET /fetch HTTP/1.1" 302 385 - "AppEngine-Google; (+http://code.google.com/appengine)" "myapp.appspot.com" ms=1747 cpu_ms=844 cpm_usd=0.000070 queue_name=__cron task_name=... loading_request=1 app_engine_release=1.8.0 instance=...
    I 2013-05-31 16:12:02.444 URL being requested: https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest?userIp=0.1.0.1
    E 2013-05-31 16:12:02.764 Building youtube object
    E 2013-05-31 16:12:02.764 Built youtube object
    E 2013-05-31 16:12:02.764 Building decorator object
    E 2013-05-31 16:12:02.764 Built decorator object
    E 2013-05-31 16:12:02.764 End static variables
    E 2013-05-31 16:12:02.764 Entering FetchHandlerPage
    I 2013-05-31 16:12:02.765 This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This requ
    

回答1:

How is cron supposed to bypass that?

Make sure the cron url is configured with login: admin and not login: required. Cron jobs "get past the login prompt" automatically. See the documentation for more information.

How can I debug what's going on?

Since a cron job is started by a GET request to a specific url, you should be able to debug the job by just making a GET request to that url and either see what errors the development server makes or see what is in the logs for the GET request.