]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WOProxyRequestHandler.m
Improved WORepetition's implementation to be more convenient in regards to the 'list...
[sope] / sope-appserver / NGObjWeb / WOProxyRequestHandler.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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
22 #include <NGObjWeb/WOProxyRequestHandler.h>
23 #include <NGObjWeb/WOApplication.h>
24 #include <NGObjWeb/WORequest.h>
25 #include <NGObjWeb/WOResponse.h>
26 #include <NGObjWeb/WOHTTPConnection.h>
27 #include "common.h"
28
29 @implementation WOProxyRequestHandler
30
31 + (int)version {
32   return [super version] + 0 /* v2 */;
33 }
34 + (void)initialize {
35   NSAssert2([super version] == 2,
36             @"invalid superclass (%@) version %i !",
37             NSStringFromClass([self superclass]), [super version]);
38 }
39
40 - (id)initWithHost:(NSString *)_hostName onPort:(unsigned int)_port {
41   if ((self = [super init])) {
42     self->client = 
43       [[WOHTTPConnection alloc] initWithHost:_hostName onPort:_port];
44     
45     self->rewriteHost = YES;
46   }
47   return self;
48 }
49
50 - (id)init {
51   return [self initWithHost:nil onPort:0];
52 }
53
54 - (void)dealloc {
55   [self->logFilePrefix release];
56   [self->client release];
57   [super dealloc];
58 }
59
60 /* settings */
61
62 - (void)enableRawLogging {
63   [self logWithFormat:@"enabling raw logging ..."];
64   self->rawLogRequest  = YES;
65   self->rawLogResponse = YES;
66 }
67
68 - (void)setLogFilePrefix:(NSString *)_p {
69   ASSIGNCOPY(self->logFilePrefix, _p);
70 }
71
72 /* logging */
73
74 - (void)logMessage:(WOMessage *)_msg prefix:(NSString *)_p 
75   ext:(NSString *)_ext
76 {
77   NSEnumerator *keys;
78   NSString     *key;
79   FILE *fh = NULL;
80   const unsigned char *s;
81   
82   if (self->logFilePrefix) {
83     NSString *fn;
84     
85     fn = [self->logFilePrefix stringByAppendingFormat:@"%04i.%@",
86               self->rqcount, _ext];
87     if ((fh = fopen([fn cString], "w")) == NULL)
88       [self logWithFormat:@"could not open: %@", fn];
89   }
90   
91   if (_p) {
92     printf("%s", [_p cString]);
93     if (fh != NULL) fprintf(fh, "%s", [_p cString]);
94   }
95   
96   /* headers */
97   keys = [[_msg headerKeys] objectEnumerator];
98   while ((key = [keys nextObject])) {
99     NSEnumerator *vals;
100     id val;
101     
102     vals = [[_msg headersForKey:key] objectEnumerator];
103     while ((val = [vals nextObject]) != NULL) {
104       s = (unsigned char *)[[val stringValue] cString];
105       printf("%s: %s\n", [key cString], s);
106       if (fh != NULL) fprintf(fh, "%s: %s\r\n", [key cString], s);
107     }
108   }
109   
110   /* content */
111   if ((s = (unsigned char *)[[_msg contentAsString] cString])) {
112     printf("\n%s\n", s);
113     if (fh != NULL) fprintf(fh, "\r\n%s", s);
114   }
115   else {
116     printf("\n");
117     if (fh != NULL) fprintf(fh, "\r\n");
118   }
119   
120   if (fh != NULL) fclose(fh);
121 }
122
123 - (void)logRequest:(WORequest *)_rq {
124   NSString *rl;
125   printf("PROXY REQUEST:---\n");
126   
127   rl = [NSString stringWithFormat:@"%@ %@ %@\r\n", 
128                    [_rq method], [_rq uri], [_rq httpVersion]];
129   [self logMessage:_rq prefix:rl ext:@"http"];
130   printf("---\n");
131 }
132
133 - (void)logResponse:(WOResponse *)_r {
134   NSString *rl;
135   printf("PROXY RESPONSE:---\n");
136   
137   rl = [NSString stringWithFormat:@"%@ %i\r\n", [_r httpVersion], [_r status]];
138   [self logMessage:_r prefix:rl ext:@"http-rs"];
139   printf("---\n");
140 }
141
142 /* dispatching */
143
144 - (WOResponse *)failedResponse:(NSString *)_txt forRequest:(WORequest *)_rq{
145   WOResponse *r;
146
147   r = [WOResponse responseWithRequest:_rq];
148   [r setStatus:500];
149   [r appendContentHTMLString:_txt];
150   return r;
151 }
152
153 - (WORequest *)fixupRequest:(WORequest *)_request {
154   return _request;
155 }
156 - (WOResponse *)fixupResponse:(WOResponse *)_r {
157   return _r;
158 }
159
160 - (WORequest *)makeProxyRequest:(WORequest *)_request url:(NSURL *)_url {
161   /* this is basically a copy with a modified URI ... */
162   WORequest *rq;
163   
164   rq = [[WORequest alloc]
165          initWithMethod:[_request method]
166          uri:[_url path]
167          httpVersion:[_request httpVersion]
168          headers:[_request headers]
169          content:[_request content]
170          userInfo:[_request userInfo]];
171   return [rq autorelease];
172 }
173
174 - (WOResponse *)handleRequest:(WORequest *)_request {
175   WOHTTPConnection *targetClient;
176   WOResponse *r;
177   
178   self->rqcount++;
179   targetClient = self->client;
180   
181   _request = [self fixupRequest:_request];
182   
183   if ([[_request uri] hasPrefix:@"http://"]) {
184     NSURL *purl;
185     
186     purl = [NSURL URLWithString:[_request uri]];
187     [self logWithFormat:@"got a proxy request: %@", purl];
188     
189     _request = [self makeProxyRequest:_request url:purl];
190     
191     targetClient = [[WOHTTPConnection alloc] initWithHost:[purl host]
192                                              onPort:[[purl port] intValue]];
193     targetClient = [targetClient autorelease];
194   }
195   
196   if (self->rawLogRequest)
197     [self logRequest:_request];
198   
199   /* force HTTP/1.0 ... */
200   [_request setHTTPVersion:@"HTTP/1.0"];
201   
202   if (![targetClient sendRequest:_request]) {
203     [self logWithFormat:@"forwarding request to client failed."];
204     return [self failedResponse:@"forwarding request to client failed."
205                  forRequest:_request];
206   }
207   
208   if ((r = [targetClient readResponse]) == nil) {
209     [self logWithFormat:@"reading response from client failed."];
210     return [self failedResponse:@"reading response from client failed."
211                  forRequest:_request];
212   }
213   
214   r = [self fixupResponse:r];
215   
216   if (self->rawLogResponse)
217     [self logResponse:r];
218   
219   return r;
220 }
221
222 /* logging */
223
224 - (NSString *)loggingPrefix {
225   return @"[proxy-handler]";
226 }
227
228 @end /* WOProxyRequestHandler */