more support for introspection paging
[Evergreen.git] / OpenSRF / src / gateway / osrf_json_gateway.c
1 #include "apachetools.h"
2 #include "opensrf/osrf_app_session.h"
3 #include "opensrf/osrf_system.h"
4 #include "objson/object.h"
5
6 #define MODULE_NAME "osrf_json_gateway_module"
7 #define GATEWAY_CONFIG "OSRFGatewayConfig"
8 #define CONFIG_CONTEXT "gateway"
9
10 #define GATEWAY_DEFAULT_CONFIG "/openils/conf/opensrf_core.xml"
11
12
13 /* our config structure */
14 typedef struct { 
15         char* configfile;  /* our bootstrap config file */
16 } osrf_json_gateway_config;
17
18 module AP_MODULE_DECLARE_DATA osrf_json_gateway_module;
19
20 char* osrf_json_gateway_config_file = NULL;
21 int bootstrapped = 0;
22
23 static const char* osrf_json_gateway_set_config(cmd_parms *parms, void *config, const char *arg) {
24         osrf_json_gateway_config  *cfg;
25         cfg = ap_get_module_config(parms->server->module_config, &osrf_json_gateway_module);
26         cfg->configfile = (char*) arg;
27         osrf_json_gateway_config_file = (char*) arg;
28         return NULL;
29 }
30
31 /* tell apache about our commands */
32 static const command_rec osrf_json_gateway_cmds[] = {
33         AP_INIT_TAKE1( GATEWAY_CONFIG, osrf_json_gateway_set_config, 
34                         NULL, RSRC_CONF, "osrf json gateway config file"),
35         {NULL}
36 };
37
38 /* build the config object */
39 static void* osrf_json_gateway_create_config( apr_pool_t* p, server_rec* s) {
40         osrf_json_gateway_config* cfg = (osrf_json_gateway_config*) 
41                         apr_palloc(p, sizeof(osrf_json_gateway_config));
42         cfg->configfile = GATEWAY_DEFAULT_CONFIG;
43         return (void*) cfg;
44 }
45
46
47 static void osrf_json_gateway_child_init(apr_pool_t *p, server_rec *s) {
48
49         char* cfg = osrf_json_gateway_config_file;
50         if( ! osrf_system_bootstrap_client( cfg, CONFIG_CONTEXT) ) {
51                 ap_log_error( APLOG_MARK, APLOG_ERR, 0, s, "Unable to Bootstrap OpenSRF Client..");
52                 return;
53         }
54         bootstrapped = 1;
55         ap_log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "Bootstrapping OpenSRF Client..");
56 }
57
58 static int osrf_json_gateway_method_handler (request_rec *r) {
59
60         /* make sure we're needed first thing*/
61         if (strcmp(r->handler, MODULE_NAME )) return DECLINED;
62
63         /* verify we are connected */
64         if( !bootstrapped || !osrf_system_get_transport_client()) {
65                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Cannot process request "
66                                 "because the OpenSRF JSON gateway has not been bootstrapped...");
67                 return HTTP_INTERNAL_SERVER_ERROR;
68         }
69
70
71         osrfLogSetAppname("osrf_json_gw");
72
73         char* service                           = NULL; /* service to connect to */
74         char* method                            = NULL; /* method to perform */
75         int api_level                           = 1;            /* request api level */
76
77         ap_set_content_type(r, "text/plain");
78
79         r->allowed |= (AP_METHOD_BIT << M_GET);
80         r->allowed |= (AP_METHOD_BIT << M_POST);
81
82         string_array* mparams   = NULL;
83         string_array* params            = apacheParseParms(r); /* free me */
84         service = apacheGetFirstParamValue( params, "service" );
85         method  = apacheGetFirstParamValue( params, "method" ); 
86         mparams = apacheGetParamValues( params, "param" ); /* free me */
87
88         if( service && method ) {
89
90                 osrfLogInfo( OSRF_LOG_MARK,  "service=%s, method=%s", service, method );
91                 osrfAppSession* session = osrf_app_client_session_init(service);
92                 int req_id = osrf_app_session_make_req( session, NULL, method, api_level, mparams );
93                 osrf_message* omsg = NULL;
94
95                 int statuscode = 200;
96
97                 /* kick off the object */
98                 ap_rputs("{\"payload\":[", r);
99
100                 int morethan1           = 0;
101                 char* statusname        = NULL;
102                 char* statustext        = NULL;
103
104                 while((omsg = osrfAppSessionRequestRecv( session, req_id, 60 ))) {
105         
106                         statuscode = omsg->status_code;
107                         jsonObject* res;        
108
109                         if( ( res = osrfMessageGetResult(omsg)) ) {
110
111                                 char* json = jsonObjectToJSON( res );
112                                 if( morethan1 ) ap_rputs(",", r); /* comma between JSON array items */
113                                 ap_rputs(json, r);
114                                 free(json);
115                                 morethan1 = 1;
116                 
117                         } else {
118         
119                                 if( statuscode > 299 ) { /* the request returned a low level error */
120                                         statusname = omsg->status_name ? strdup(omsg->status_name) : strdup("Unknown Error");
121                                         statustext = omsg->status_text ? strdup(omsg->status_text) : strdup("No Error Message");
122                                         osrfLogError( OSRF_LOG_MARK,  "Gateway received error: %s", statustext );
123                                 }
124                         }
125         
126                         osrf_message_free(omsg);
127                         if(statusname) break;
128                 }
129
130                 ap_rputs("]",r); /* finish off the payload array */
131
132                 if(statusname) {
133
134                         /* add a debug field if the request died */
135                         ap_log_rerror( APLOG_MARK, APLOG_INFO, 0, r, 
136                                         "OpenSRF JSON Request returned error: %s -> %s", statusname, statustext );
137                         int l = strlen(statusname) + strlen(statustext) + 24;
138                         char buf[l];
139                         bzero(buf,l);
140                         snprintf( buf, l, ",\"debug\":\"%s : %s\"", statusname, statustext );
141                         ap_rputs(buf, r);
142
143                         free(statusname);
144                         free(statustext);
145                 }
146
147                 /* insert the statu code */
148                 char buf[24];
149                 bzero(buf,24);
150                 snprintf(buf, 24, ",\"status\":%d", statuscode );
151                 ap_rputs( buf, r );
152
153                 ap_rputs( "}", r ); /* finish off the object */
154                 osrf_app_session_destroy(session);
155         }
156
157         string_array_destroy(params);
158         string_array_destroy(mparams);
159
160         return OK;
161 }
162
163 static void osrf_json_gateway_register_hooks (apr_pool_t *p) {
164         ap_hook_handler(osrf_json_gateway_method_handler, NULL, NULL, APR_HOOK_MIDDLE);
165         ap_hook_child_init(osrf_json_gateway_child_init,NULL,NULL,APR_HOOK_MIDDLE);
166 }
167
168
169 module AP_MODULE_DECLARE_DATA osrf_json_gateway_module = {
170         STANDARD20_MODULE_STUFF,
171         NULL,
172         NULL,
173         osrf_json_gateway_create_config,
174         NULL,
175         osrf_json_gateway_cmds,
176         osrf_json_gateway_register_hooks,
177 };
178
179
180
181