added code for SRU GET/POST/SOAP determination.
[metaproxy-moved-to-github.git] / src / filter_sru_to_z3950.cpp
1 /* $Id: filter_sru_to_z3950.cpp,v 1.3 2006-09-13 21:49:34 marc Exp $
2    Copyright (c) 2005-2006, Index Data.
3
4    See the LICENSE file for details
5  */
6
7 #include "config.hpp"
8 #include "filter.hpp"
9 #include "package.hpp"
10 #include "util.hpp"
11 #include "filter_sru_to_z3950.hpp"
12
13 #include <yaz/zgdu.h>
14 #include <yaz/srw.h>
15
16 #include <boost/thread/mutex.hpp>
17
18 #include <iostream>
19 #include <sstream>
20 #include <string>
21
22
23 namespace mp = metaproxy_1;
24 namespace yf = mp::filter;
25
26 namespace metaproxy_1 
27 {
28
29     template<typename T>
30     std::string stringify(const T& x)
31     {
32         std::ostringstream o;
33         o << x;
34         return o.str();
35     }
36 }
37
38
39 namespace metaproxy_1 {
40     namespace filter {
41         class SRUtoZ3950::Rep {
42             //friend class SRUtoZ3950;
43         public:
44             void configure(const xmlNode *xmlnode);
45             void process(metaproxy_1::Package &package) const;
46         private:
47             std::string protocol_type(const Z_HTTP_Request &http_req) const;
48             std::string debug_http(const Z_HTTP_Request &http_req) const;
49             void http_response(metaproxy_1::Package &package, 
50                                const std::string &content, 
51                                int http_code = 200) const;
52         };
53     }
54 }
55
56 yf::SRUtoZ3950::SRUtoZ3950() : m_p(new Rep)
57 {
58 }
59
60 yf::SRUtoZ3950::~SRUtoZ3950()
61 {  // must have a destructor because of boost::scoped_ptr
62 }
63
64 void yf::SRUtoZ3950::configure(const xmlNode *xmlnode)
65 {
66     m_p->configure(xmlnode);
67 }
68
69 void yf::SRUtoZ3950::process(mp::Package &package) const
70 {
71     m_p->process(package);
72 }
73
74 void yf::SRUtoZ3950::Rep::configure(const xmlNode *xmlnode)
75 {
76 }
77
78 void yf::SRUtoZ3950::Rep::process(mp::Package &package) const
79 {
80     Z_GDU *zgdu_req = package.request().get();
81
82     // ignoring all non HTTP_Request packages
83     if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
84         package.move();
85         return;
86     }
87
88
89  
90     
91     // only working on  HTTP_Request packages now
92     Z_HTTP_Request* http_req =  zgdu_req->u.HTTP_Request;
93
94     // TODO: SRU package checking and translation to Z3950 package
95  
96     std::cout << protocol_type(*http_req) << "\n";
97
98     package.move();
99     return;
100
101
102
103 //     int ret_code = 2;  /* 2=NOT TAKEN, 1=TAKEN, 0=SOAP TAKEN */
104 //     Z_SRW_PDU *sru_res = 0;
105 //     Z_SOAP *soap_package = 0;
106 //     char *charset = 0;
107 //     Z_SRW_diagnostic *diagnostic = 0;
108 //     int num_diagnostic = 0;
109 //     mp::odr odr;
110     
111 //     ret_code = yaz_sru_decode(http_req, &sru_res, 
112 //                                    &soap_package, odr, &charset,
113 //                                    &diagnostic, &num_diagnostic)))
114 //      
115 //     ret_code = yaz_srw_decode(http_req, &sru_res, 
116 //                                         &soap_package, odr, &charset)))
117
118     
119
120
121     // sending Z3950 package through pipeline
122     package.move();
123
124
125     // TODO: Z3950 response parsing and translation to SRU package
126     Z_HTTP_Response* http_res = 0;
127
128     std::string content = debug_http(*http_req);
129     int http_code = 200;
130     
131     http_response(package, content, http_code);
132
133     //package.response() = zgdu_res;
134 }
135
136 std::string 
137 yf::SRUtoZ3950::Rep::protocol_type(const Z_HTTP_Request &http_req) const
138 {
139     std::string protocol("HTTP");
140
141     const std::string mime_text_xml("text/xml");
142     const std::string mime_soap_xml("application/soap+xml");
143     const std::string mime_urlencoded("application/x-www-form-urlencoded");
144
145     const std::string http_method(http_req.method);
146
147     //const std::string http_type(z_HTTP_header_lookup(http_req.headers, 
148     //                                               "Content-Type"));
149     // TODO: there is a sude condition in the above, fix it in YAZ
150     const std::string http_type("xyz");
151
152     if (http_method == "GET")
153         return "SRU GET";
154
155     if (http_method == "POST"
156               && http_type  == mime_urlencoded)
157         return "SRU POST";
158     
159     if ( http_method == "POST"
160          && (http_type  == mime_text_xml
161              || http_type  == mime_soap_xml))
162         return "SRU SOAP";
163
164     return "HTTP";
165 }
166
167 std::string 
168 yf::SRUtoZ3950::Rep::debug_http(const Z_HTTP_Request &http_req) const
169 {
170     std::string message("<html>\n<body>\n<h1>"
171                         "Metaproxy SRUtoZ3950 filter"
172                         "</h1>\n");
173     
174     message += "<h3>HTTP Info</h3><br/>\n";
175     message += "<p>\n";
176     message += "<b>Method: </b> " + std::string(http_req.method) + "<br/>\n";
177     message += "<b>Version:</b> " + std::string(http_req.version) + "<br/>\n";
178     message += "<b>Path:   </b> " + std::string(http_req.path) + "<br/>\n";
179     message += "<b>Content-Type:</b>"
180         + std::string(z_HTTP_header_lookup(http_req.headers, "Content-Type"))
181         + "<br/>\n";
182     message += "<b>Content-Length:</b>"
183         + std::string(z_HTTP_header_lookup(http_req.headers, 
184                                            "Content-Length"))
185         + "<br/>\n";
186     message += "</p>\n";    
187     
188     message += "<h3>Headers</h3><br/>\n";
189     message += "<p>\n";    
190     Z_HTTP_Header* header = http_req.headers;
191     while (header){
192         message += "<b>Header: </b> <i>" 
193             + std::string(header->name) + ":</i> "
194             + std::string(header->value) + "<br/>\n";
195         header = header->next;
196     }
197     message += "</p>\n";    
198     message += "</body>\n</html>\n";
199     return message;
200 }
201
202 void yf::SRUtoZ3950::Rep::http_response(metaproxy_1::Package &package, 
203                                         const std::string &content, 
204                                         int http_code) const
205 {
206
207     Z_GDU *zgdu_req = package.request().get(); 
208     Z_GDU *zgdu_res = 0; 
209     mp::odr odr;
210     zgdu_res 
211        = odr.create_HTTP_Response(package.session(), 
212                                   zgdu_req->u.HTTP_Request, 
213                                   http_code);
214         
215     zgdu_res->u.HTTP_Response->content_len = content.size();
216     zgdu_res->u.HTTP_Response->content_buf 
217         = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len);
218     
219     strncpy(zgdu_res->u.HTTP_Response->content_buf, 
220             content.c_str(),  zgdu_res->u.HTTP_Response->content_len);
221     
222     //z_HTTP_header_add(odr, &hres->headers,
223     //                  "Content-Type", content_type.c_str());
224     package.response() = zgdu_res;
225 }
226
227
228
229
230 static mp::filter::Base* filter_creator()
231 {
232     return new mp::filter::SRUtoZ3950;
233 }
234
235 extern "C" {
236     struct metaproxy_1_filter_struct metaproxy_1_filter_sru_to_z3950 = {
237         0,
238         "SRUtoZ3950",
239         filter_creator
240     };
241 }
242
243
244 /*
245  * Local variables:
246  * c-basic-offset: 4
247  * indent-tabs-mode: nil
248  * c-file-style: "stroustrup"
249  * End:
250  * vim: shiftwidth=4 tabstop=8 expandtab
251  */