2 //=============================================================================
4 * @file http_handler.cpp
8 //=============================================================================
11 #include "ace/OS_NS_stdio.h"
12 #include "ace/OS_NS_string.h"
13 #include "ace/Filecache.h"
14 #include "http_handler.h"
16 HTTP_Handler::HTTP_Handler ()
20 HTTP_Handler::HTTP_Handler (const char * path
)
22 // How long is the request going to be?
23 this->request_
[0] = '\0';
25 ACE_OS::strlen ("GET ")
26 + ACE_OS::strlen (path
)
27 + ACE_OS::strlen (" HTTP/1.0\r\nAccept: HTTP/1.0\r\n\r\n");
30 if ((u_int
) this->request_size_
< sizeof (this->request_
))
31 ACE_OS::sprintf (this->request_
,
32 "GET %s HTTP/1.0\r\nAccept: HTTP/1.0\r\n\r\n",
36 const char *last
= ACE_OS::strrchr (path
, '/');
40 else if (last
[1] == '\0')
45 ACE_OS::sprintf (this->filename_
, "%s", last
);
49 HTTP_Handler::open (void *)
51 // If you want threads, use the activate stuff.
53 if (this->activate () != 0)
55 ACE_ERROR_RETURN ((LM_ERROR
, "HTTP_Handler::open, whups!\n"), -1);
67 static char buf
[BUFSIZ
];
70 ACE_DEBUG ((LM_DEBUG
, "[%t] sending request --\n%s", this->request_
));
72 this->peer ().send_n (this->request_
, this->request_size_
);
74 // Read in characters until encounter \r\n\r\n
80 while (((count
+= this->peer ().recv_n (buf
+ count
, 1)) > 0)
81 && ((u_int
) count
< sizeof (buf
)))
87 done
= ACE_OS::strcmp (buf
+ count
- 4, "\n\n") == 0;
95 done
= ACE_OS::strcmp (buf
+ count
- 4, "\r\n\r\n") == 0;
103 char *last
= ACE_OS::strrchr (buf
, '\n');
106 if ((contentlength
= ACE_OS::strstr (buf
, "\nContent-length:"))
107 || (contentlength
= ACE_OS::strstr (buf
, "\nContent-Length:")))
112 count
= ACE_OS::strlen (last
);
113 ACE_OS::memmove (buf
, last
, count
+ 1);
118 contentlength
= ACE_OS::strstr (buf
, "\nContent-length:");
122 ACE_OS::strstr (buf
, "\nContent-Length:");
128 // ASSERT (contentlength != 0)
131 && (::sscanf (contentlength
, "\nContent-%*[lL]ength: %d ",
134 this->response_size_
= size
;
135 ACE_Filecache_Handle
afh (ACE_TEXT_CHAR_TO_TCHAR (this->filename_
),
136 this->response_size_
);
138 this->peer ().recv_n (afh
.address (), this->response_size_
);
140 ACE_DEBUG ((LM_DEBUG
,
141 " ``%s'' is now cached.\n",
146 // Maybe we should do something more clever here, such as extend
147 // ACE_Filecache_Handle to allow the creation of cache objects
148 // whose size is unknown?
150 // Another possibility is to write the contents out to a file,
151 // and then cache it.
153 // Perhaps make ACE_Filecache_Handle more savvy, and allow a
154 // constructor which accepts a PEER as a parameter.
155 ACE_DEBUG ((LM_DEBUG
,
156 "HTTP_Handler, no content-length header!\n"));
163 HTTP_Handler::filename () const
165 return this->filename_
;
169 HTTP_Connector::connect (const char * url
)
175 if (this->parseurl (url
, host
, &port
, path
) == -1)
177 ACE_DEBUG ((LM_DEBUG
,
178 "HTTP_Connector, error parsing url: %s\n",
183 HTTP_Handler
hh (path
);
184 HTTP_Handler
*hhptr
= &hh
;
186 // First check the cache.
187 if (ACE_Filecache::instance ()->find (ACE_TEXT_CHAR_TO_TCHAR (hh
.filename ())) == 0)
189 ACE_DEBUG ((LM_DEBUG
, " ``%s'' is already cached.\n",
194 return this->connector_
.connect (hhptr
, ACE_INET_Addr (port
, host
));
197 #define DEFAULT_SERVER_PORT 80
199 // extract the main components of a URL
201 HTTP_Connector::parseurl (const char *url
,
208 // hackish, but useful
209 if (3 != ::sscanf (url
, "http://%[^:/]:%hu%s", host
, port
, path
))
211 if (2 != ::sscanf (url
, "http://%[^:/]:%hu", host
, port
))
213 if (2 != ::sscanf (url
, "http://%[^:/]%s", host
, path
))
215 if (1 != ::sscanf (url
, "http://%[^:/]", host
))
219 *port
= DEFAULT_SERVER_PORT
;
220 ACE_OS::strcpy (path
, "/");
224 *port
= DEFAULT_SERVER_PORT
;
226 else ACE_OS::strcpy (path
, "/");