Monday, August 8, 2011

Google Reports API (Authentication)

At CSU, Chico the student email service is hosted through Google, so we can use all kinds of cool Google APIs to pull down and analyze data. Since we use Oracle databases, I found a way to query and analyze Google Reporting Services in a PL/SQL package.

1) Get an authentication token
Google will provide 3 different kinds of auth tokens, but with a little regexp adjustment, I've provided a method to pull out either the SID or AUTH types.  Simply pass either of those strings into the TOKEN_TYPE parameter.

FUNCTION FETCH_POST_TOKEN
              (
                            V_AUTH1    VARCHAR2
                           ,V_AUTH2    VARCHAR2
                           ,V_SERVICE  VARCHAR2
                           ,TOKEN_TYPE VARCHAR2
              ) RETURN VARCHAR2 IS
                            PRAGMA AUTONOMOUS_TRANSACTION;
                            /***
                            ** Function: FETCH_POST_TOKEN
                            ** Params:  V_AUTH1, V_AUTH2, V_SERVICE = credentials used to obtain auth token, TOKEN_TYPE =
                            **              determines which regexp to use in order to get right token.
                            ** Returns: auth token of choice as a varchar2
                            ** Description: Sends an http request to the Google reporting API in order to obtain an auth token.
                            **                  reads the response back and returns the appropriate auth token.
                            ***/
                            --declare variables
                            L_REQUEST  UTL_HTTP.REQ;
                            L_RESPONSE UTL_HTTP.RESP;
                            L_PARAMS   VARCHAR2(255);
                            AUTH_TOKEN VARCHAR2(2000);
                            V_RESP_BOD VARCHAR2(1000);
           
              BEGIN
                            -- set up the request body with our credentials
                            L_PARAMS := 'accountType=HOSTED&Email=' || V_AUTH1 || '&' || 'Passwd=' || V_AUTH2 || '&' || 'service=' || V_SERVICE || '&' ||
                                        'source=/*your source here*/';
                            L_REQUEST := UTL_HTTP.BEGIN_REQUEST('https://www.google.com/accounts/ClientLogin', 'POST', 'HTTP/1.1');
           
                            -- request headers setup
                            UTL_HTTP.SET_HEADER(L_REQUEST, 'Content-Type', 'application/x-www-form-urlencoded');
           
                            UTL_HTTP.SET_HEADER(L_REQUEST, 'Content-Length', LENGTH(L_PARAMS));
                            -- end of request headers setup
           
                            -- write out the request body
                            UTL_HTTP.WRITE_TEXT(L_REQUEST, L_PARAMS);
           
                            -- request/get the response
                            L_RESPONSE := UTL_HTTP.GET_RESPONSE(R => L_REQUEST);
                            UTL_HTTP.READ_TEXT(R => L_RESPONSE, DATA => V_RESP_BOD);
                            IF L_RESPONSE.STATUS_CODE = 200
                            THEN
                                          --Response 200: 'OK'
                                          --gather entire response (a bunch of crap plus the much needed "auth token" (aka an encrypted string)
                                          --UTL_HTTP.READ_TEXT(R => L_RESPONSE, DATA => V_RESP_BOD);
                         
                                          IF (TOKEN_TYPE = 'SID')
                                          THEN
                                                        --Assumes that sid= will be first 4 characters of the string.
                                                        AUTH_TOKEN := REGEXP_SUBSTR(V_RESP_BOD, '.*$?', 5);
                                          END IF;
                                          IF (TOKEN_TYPE = 'AUTH')
                                          THEN
                                                        --Use some fancy REGEX to parse the response, gathering the auth token into our variable
                                                        AUTH_TOKEN := SUBSTR(REGEXP_SUBSTR(V_RESP_BOD, 'Auth=([[:print:]]+)/?'), 6);
                                          END IF;
                                          --Insert into our auth table to store token. Prevents uneccesary auth calls.
                                          --Here we insert into a table, as each auth_token will last for 24 hours, preventing
                                          --redundant auth calls.
                            ELSE
                                          -- otherwise return 'error', something happened!
                                          AUTH_TOKEN := SUBSTR(V_RESP_BOD, 1, 1500);
                                          --DBMS_OUTPUT.PUT_LINE(AUTH_TOKEN);
                            END IF;
                            -- end the response
                            UTL_HTTP.END_RESPONSE(R => L_RESPONSE);
           
                            COMMIT;
                            -- return the auth token, otherwise 'error' (as determined above)
                            RETURN(AUTH_TOKEN);
           
              END;

No comments:

Post a Comment