]> err.no Git - sope/blob - skyrix-sope/NGObjWeb/WOProxyRequestHandler.m
added svn:keywords and svn:ignore where appropriate. removed CVS artifacts.
[sope] / skyrix-sope / NGObjWeb / WOProxyRequestHandler.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include <NGObjWeb/WOProxyRequestHandler.h>
24 #include <NGObjWeb/WOApplication.h>
25 #include <NGObjWeb/WORequest.h>
26 #include <NGObjWeb/WOResponse.h>
27 #include <NGObjWeb/WOHTTPConnection.h>
28 #include "common.h"
29
30 @implementation WOProxyRequestHandler
31
32 + (int)version {
33   return [super version] + 0 /* v2 */;
34 }
35 + (void)initialize {
36   NSAssert2([super version] == 2,
37             @"invalid superclass (%@) version %i !",
38             NSStringFromClass([self superclass]), [super version]);
39 }
40
41 - (id)initWithHost:(NSString *)_hostName onPort:(unsigned int)_port {
42   if ((self = [super init])) {
43     self->client = 
44       [[WOHTTPConnection alloc] initWithHost:_hostName onPort:_port];
45     
46     self->rewriteHost = YES;
47   }
48   return self;
49 }
50
51 - (id)init {
52   return [self initWithHost:nil onPort:0];
53 }
54
55 - (void)dealloc {
56   [self->logFilePrefix release];
57   [self->client release];
58   [super dealloc];
59 }
60
61 /* settings */
62
63 - (void)enableRawLogging {
64   [self logWithFormat:@"enabling raw logging ..."];
65   self->rawLogRequest  = YES;
66   self->rawLogResponse = YES;
67 }
68
69 - (void)setLogFilePrefix:(NSString *)_p {
70   ASSIGNCOPY(self->logFilePrefix, _p);
71 }
72
73 /* logging */
74
75 - (void)logMessage:(WOMessage *)_msg prefix:(NSString *)_p 
76   ext:(NSString *)_ext
77 {
78   NSEnumerator *keys;
79   NSString     *key;
80   FILE *fh = NULL;
81   const unsigned char *s;
82   
83   if (self->logFilePrefix) {
84     NSString *fn;
85     
86     fn = [self->logFilePrefix stringByAppendingFormat:@"%04i.%@",
87               self->rqcount, _ext];
88     if ((fh = fopen([fn cString], "w")) == NULL)
89       [self logWithFormat:@"could not open: %@", fn];
90   }
91   
92   if (_p) {
93     printf("%s", [_p cString]);
94     if (fh) fprintf(fh, "%s", [_p cString]);
95   }
96   
97   /* headers */
98   keys = [[_msg headerKeys] objectEnumerator];
99   while ((key = [keys nextObject])) {
100     NSEnumerator *vals;
101     id val;
102     
103     vals = [[_msg headersForKey:key] objectEnumerator];
104     while ((val = [vals nextObject])) {
105       s = [[val stringValue] cString];
106       printf("%s: %s\n", [key cString], s);
107       if (fh) fprintf(fh, "%s: %s\r\n", [key cString], s);
108     }
109   }
110   
111   /* content */
112   if ((s = [[_msg contentAsString] cString])) {
113     printf("\n%s\n", s);
114     if (fh) fprintf(fh, "\r\n%s", s);
115   }
116   else {
117     printf("\n");
118     if (fh) fprintf(fh, "\r\n");
119   }
120   
121   if (fh) fclose(fh);
122 }
123
124 - (void)logRequest:(WORequest *)_rq {
125   NSString *rl;
126   printf("PROXY REQUEST:---\n");
127   
128   rl = [NSString stringWithFormat:@"%@ %@ %@\r\n", 
129                    [_rq method], [_rq uri], [_rq httpVersion]];
130   [self logMessage:_rq prefix:rl ext:@"http"];
131   printf("---\n");
132 }
133
134 - (void)logResponse:(WOResponse *)_r {
135   NSString *rl;
136   printf("PROXY RESPONSE:---\n");
137   
138   rl = [NSString stringWithFormat:@"%@ %i\r\n", [_r httpVersion], [_r status]];
139   [self logMessage:_r prefix:rl ext:@"http-rs"];
140   printf("---\n");
141 }
142
143 /* dispatching */
144
145 - (WOResponse *)failedResponse:(NSString *)_txt forRequest:(WORequest *)_rq{
146   WOResponse *r;
147
148   r = [WOResponse responseWithRequest:_rq];
149   [r setStatus:500];
150   [r appendContentHTMLString:_txt];
151   return r;
152 }
153
154 - (WORequest *)fixupRequest:(WORequest *)_request {
155   return _request;
156 }
157 - (WOResponse *)fixupResponse:(WOResponse *)_r {
158   return _r;
159 }
160
161 - (WORequest *)makeProxyRequest:(WORequest *)_request url:(NSURL *)_url {
162   /* this is basically a copy with a modified URI ... */
163   WORequest *rq;
164   
165   rq = [[WORequest alloc]
166          initWithMethod:[_request method]
167          uri:[_url path]
168          httpVersion:[_request httpVersion]
169          headers:[_request headers]
170          content:[_request content]
171          userInfo:[_request userInfo]];
172   return [rq autorelease];
173 }
174
175 - (WOResponse *)handleRequest:(WORequest *)_request {
176   WOHTTPConnection *targetClient;
177   WOResponse *r;
178   
179   self->rqcount++;
180   targetClient = self->client;
181   
182   _request = [self fixupRequest:_request];
183   
184   if ([[_request uri] hasPrefix:@"http://"]) {
185     NSURL *purl;
186     
187     purl = [NSURL URLWithString:[_request uri]];
188     [self logWithFormat:@"got a proxy request: %@", purl];
189     
190     _request = [self makeProxyRequest:_request url:purl];
191     
192     targetClient = [[WOHTTPConnection alloc] initWithHost:[purl host]
193                                              onPort:[[purl port] intValue]];
194     targetClient = [targetClient autorelease];
195   }
196   
197   if (self->rawLogRequest)
198     [self logRequest:_request];
199   
200   /* force HTTP/1.0 ... */
201   [_request setHTTPVersion:@"HTTP/1.0"];
202   
203   if (![targetClient sendRequest:_request]) {
204     [self logWithFormat:@"forwarding request to client failed."];
205     return [self failedResponse:@"forwarding request to client failed."
206                  forRequest:_request];
207   }
208   
209   if ((r = [targetClient readResponse]) == nil) {
210     [self logWithFormat:@"reading response from client failed."];
211     return [self failedResponse:@"reading response from client failed."
212                  forRequest:_request];
213   }
214   
215   r = [self fixupResponse:r];
216   
217   if (self->rawLogResponse)
218     [self logResponse:r];
219   
220   return r;
221 }
222
223 /* logging */
224
225 - (NSString *)loggingPrefix {
226   return @"[proxy-handler]";
227 }
228
229 @end /* WOProxyRequestHandler */