|
From: <at...@us...> - 2007-08-22 17:46:36
|
Revision: 484
http://cadcdev.svn.sourceforge.net/cadcdev/?rev=484&view=rev
Author: atani
Date: 2007-08-22 10:46:32 -0700 (Wed, 22 Aug 2007)
Log Message:
-----------
updates to support POST requests
Modified Paths:
--------------
tiki/examples/net/httpclient/src/main.cpp
tiki/include/Tiki/net/buffer.h
tiki/include/Tiki/net/http/request.h
tiki/include/Tiki/net/http/useragent.h
tiki/src/net/http/request.cpp
tiki/src/net/http/useragent.cpp
Modified: tiki/examples/net/httpclient/src/main.cpp
===================================================================
--- tiki/examples/net/httpclient/src/main.cpp 2007-08-22 00:39:13 UTC (rev 483)
+++ tiki/examples/net/httpclient/src/main.cpp 2007-08-22 17:46:32 UTC (rev 484)
@@ -53,6 +53,7 @@
{
RefPtr<Buffer> responseBuf = response->getContentPart(*iter);
Tiki::Debug::printf("Content Part: %s [%u bytes]\n", (*iter).c_str(), responseBuf->getUsedDataLen());
+ Tiki::Debug::printf("%s\n", responseBuf->getData());
}
Modified: tiki/include/Tiki/net/buffer.h
===================================================================
--- tiki/include/Tiki/net/buffer.h 2007-08-22 00:39:13 UTC (rev 483)
+++ tiki/include/Tiki/net/buffer.h 2007-08-22 17:46:32 UTC (rev 484)
@@ -10,6 +10,8 @@
#include "Tiki/object.h"
+#include <fstream>
+
namespace Tiki {
namespace Net {
@@ -17,13 +19,14 @@
class Buffer : public Object
{
public:
- Buffer(size_t len) {
+ Buffer(size_t len, std::string contentType = "application/octet-stream") : m_contentType(contentType) {
m_data = new uint8[len];
memset(m_data, 0, len);
m_dataLen = len;
m_usedDataLen = 0;
}
- Buffer(size_t len, uint8 *data) {
+
+ Buffer(size_t len, uint8 *data, std::string contentType = "application/octet-stream") : m_contentType(contentType) {
m_data = new uint8[len];
memset(m_data, 0, len);
m_dataLen = len;
@@ -31,6 +34,16 @@
memcpy(m_data, data, len);
}
+ Buffer(std::string filename, std::string contentType, std::string fieldName = "") : m_fileName(filename), m_contentType(contentType), m_fieldName(fieldName) {
+ std::ifstream stream(filename.c_str(), std::ios::in | std::ios::binary);
+ stream.seekg(0, std::ios::end);
+ m_dataLen = m_usedDataLen = stream.tellg();
+ stream.seekg(0);
+ m_data = new uint8[m_dataLen];
+ stream.read((char *)m_data, m_dataLen);
+ stream.close();
+ }
+
void append(RefPtr<Buffer> buf) {
uint8 * newbuf = new uint8[ m_dataLen + buf->getDataLen() ];
memcpy(newbuf, m_data, m_usedDataLen);
@@ -50,6 +63,29 @@
return m_data;
}
+ std::string getContentType() const {
+ return m_contentType;
+ }
+
+ std::string getFileName() const {
+ return m_fileName;
+ }
+
+ std::string getFileNameShort() const {
+ std::string filename = m_fileName;
+ while(filename.find("/") != std::string::npos) {
+ filename = filename.substr(filename.find("/") + 1);
+ }
+ while(filename.find("\\") != std::string::npos) {
+ filename = filename.substr(filename.find("\\") + 1);
+ }
+ return filename;
+ }
+
+ std::string getFieldName() const {
+ return m_fieldName;
+ }
+
size_t getDataLen() const {
return m_dataLen;
}
@@ -73,6 +109,9 @@
}
private:
+ std::string m_contentType;
+ std::string m_fileName;
+ std::string m_fieldName;
uint8 *m_data;
size_t m_dataLen;
size_t m_usedDataLen;
Modified: tiki/include/Tiki/net/http/request.h
===================================================================
--- tiki/include/Tiki/net/http/request.h 2007-08-22 00:39:13 UTC (rev 483)
+++ tiki/include/Tiki/net/http/request.h 2007-08-22 17:46:32 UTC (rev 484)
@@ -38,8 +38,13 @@
std::list<std::string> getContentPartNames() const;
RefPtr<Buffer> getContentPart(std::string name) const;
+ std::string getBoundaryMarker() const {
+ return m_boundaryMarker;
+ }
+
private:
std::string m_url;
+ std::string m_boundaryMarker;
typedef std::map<std::string, std::string> StringStringMap;
typedef std::map<std::string, RefPtr< Buffer > > StringBufferMap;
StringStringMap m_params;
Modified: tiki/include/Tiki/net/http/useragent.h
===================================================================
--- tiki/include/Tiki/net/http/useragent.h 2007-08-22 00:39:13 UTC (rev 483)
+++ tiki/include/Tiki/net/http/useragent.h 2007-08-22 17:46:32 UTC (rev 484)
@@ -9,6 +9,7 @@
#define __TIKI_NET_HTTP_USERAGENT_H
#include "Tiki/refcnt.h"
+#include "Tiki/net/tcpsocket.h"
#include "Tiki/net/http/cookie.h"
#include "Tiki/net/http/request.h"
#include "Tiki/net/http/response.h"
@@ -19,6 +20,8 @@
namespace Http {
+using Tiki::Net::TCP::TCPSocket;
+
class HttpUserAgent : public RefCnt {
public:
@@ -52,9 +55,9 @@
return m_cookies;
}
- RefPtr<Response> get(RefPtr<Request> req) const;
+ RefPtr<Response> get(RefPtr<Request> req);
- RefPtr<Response> post(RefPtr<Request> req) const;
+ RefPtr<Response> post(RefPtr<Request> req);
private:
std::string m_userAgentName;
@@ -62,6 +65,11 @@
int m_proxyPort;
std::list< RefPtr< Cookie > > m_cookies;
+ void parseUrl(const std::string url, std::string &host, std::string &resource, int &port);
+ void buildRequest(const std::string host, const std::string resource, const int port,
+ const std::string mode, RefPtr<Request> request, std::string &requestText,
+ RefPtr<Address> address);
+ void readResponse(RefPtr<Response> response, RefPtr<TCPSocket> socket);
};
Modified: tiki/src/net/http/request.cpp
===================================================================
--- tiki/src/net/http/request.cpp 2007-08-22 00:39:13 UTC (rev 483)
+++ tiki/src/net/http/request.cpp 2007-08-22 17:46:32 UTC (rev 484)
@@ -20,6 +20,8 @@
Request::Request() {
setHeaderParam("Connection", "close");
+ m_boundaryMarker = "-----------------------09f911019d74e35bd84156c5635688c0";
+
}
void Request::setHeaderParam(std::string param, std::string value) {
Modified: tiki/src/net/http/useragent.cpp
===================================================================
--- tiki/src/net/http/useragent.cpp 2007-08-22 00:39:13 UTC (rev 483)
+++ tiki/src/net/http/useragent.cpp 2007-08-22 17:46:32 UTC (rev 484)
@@ -11,6 +11,7 @@
#include "Tiki/net/http/useragent.h"
#include <sstream>
+#include <math.h>
namespace Tiki {
@@ -47,79 +48,209 @@
setProxyPort(8080);
}
-RefPtr<Response> HttpUserAgent::get(RefPtr<Request> req) const {
+RefPtr<Response> HttpUserAgent::get(RefPtr<Request> req) {
RefPtr<TCPSocket> socket = new TCPSocket();
socket->setNonBlocking(false);
RefPtr<Response> response = new Response();
response->setUrl(req->getUrl());
response->setResultCode(200);
- std::string url = req->getUrl();
- std::string hostname = "";
- int port = 80;
- std::string resource = "/index.html";
+ std::string hostname;
+ int port;
+ std::string resource;
- if(url.find("http://") == 0) {
- url = url.substr(std::string("http://").length());
+ parseUrl(req->getUrl(), hostname, resource, port);
+
+ RefPtr<Address> requestAddress = new Address();
+
+ std::string requestText;
+ buildRequest(hostname, resource, port, "GET", req, requestText, requestAddress);
+ socket->setPeerAddress(requestAddress);
+ Tiki::Debug::printf("Request:\n%s", requestText.c_str());
+
+ socket->open();
+ if(socket->isOpen()) {
+ Tiki::Debug::printf("Sending request...\n");
}
- else if(url.find("https://") == 0) {
- url = url.substr(std::string("https://").length());
+ else {
+ Tiki::Debug::printf("connect failed\n");
+ response->setResultCode(504);
+ return response;
}
- hostname = url.substr(0, url.find("/"));
- if(url.find("/") != std::string::npos) {
- resource = url.substr(url.find("/"));
+
+ RefPtr<Buffer> buf = new Buffer(2048);
+ buf->setData((uint8 *)requestText.c_str(), requestText.size());
+ socket->send(buf);
+
+ readResponse(response, socket);
+
+ return response;
+}
+
+RefPtr<Response> HttpUserAgent::post(RefPtr<Request> req) {
+ RefPtr<TCPSocket> socket = new TCPSocket();
+ socket->setNonBlocking(false);
+ RefPtr<Response> response = new Response();
+ response->setUrl(req->getUrl());
+ response->setResultCode(200);
+
+ std::string hostname;
+ int port;
+ std::string resource;
+
+ parseUrl(req->getUrl(), hostname, resource, port);
+
+ RefPtr<Address> requestAddress = new Address();
+
+ std::string requestText;
+ buildRequest(hostname, resource, port, "POST", req, requestText, requestAddress);
+ socket->setPeerAddress(requestAddress);
+ Tiki::Debug::printf("Request:\n%s", requestText.c_str());
+
+ socket->open();
+ if(socket->isOpen()) {
+ Tiki::Debug::printf("Sending request...\n");
}
- if(hostname.find(":") != std::string::npos) {
- std::string portstr = url.substr(hostname.find(":"));
+ else {
+ Tiki::Debug::printf("connect failed\n");
+ response->setResultCode(504);
+ return response;
+ }
+
+ RefPtr<Buffer> buf = new Buffer(2048);
+ buf->setData((uint8 *)requestText.c_str(), requestText.size());
+ socket->send(buf);
+
+ std::list<std::string> content = req->getContentPartNames();
+ if(content.size() > 1) {
+ for(std::list<std::string>::iterator iter = content.begin();
+ iter != content.end();
+ ++iter) {
+ RefPtr<Buffer> buf = req->getContentPart(*iter);
+ std::stringstream temp;
+ temp << req->getBoundaryMarker() << "\r\n";
+ temp << "Content-Disposition: form-data: name=\"";
+ if(buf->getFieldName().size() > 0) {
+ temp << buf->getFieldName();
+ }
+ else {
+ temp << "File";
+ }
+ temp << "\"; filename=\"" << buf->getFileNameShort() << "\"\r\nContent-Type: " << buf->getContentType() << "\r\n";
+ RefPtr<Buffer> headerBuf = new Buffer(2048);
+ std::string headerText = temp.str();
+ headerBuf->setData((uint8 *)headerText.c_str(), headerText.size());
+ socket->send(headerBuf);
+ socket->send(buf);
+ }
+ std::string footerText = req->getBoundaryMarker();
+ footerText.append("--\r\n");
+ RefPtr<Buffer> footerBuf = new Buffer(2048);
+ footerBuf->setData((uint8 *)footerText.c_str(), footerText.size());
+ socket->send(footerBuf);
+ }
+ else if(content.size() == 1) {
+ RefPtr<Buffer> buf = req->getContentPart(*content.begin());
+ socket->send(buf);
+ }
+
+ readResponse(response, socket);
+
+ return response;
+}
+
+void HttpUserAgent::parseUrl(const std::string url, std::string &host, std::string &resource, int &port) {
+ std::string temp_url = url;
+
+ // set defaults
+ host = "";
+ port = 80;
+ resource = "/index.html";
+
+ if(temp_url.find("http://") == 0) {
+ temp_url = temp_url.substr(std::string("http://").length());
+ }
+ else if(temp_url.find("https://") == 0) {
+ temp_url = temp_url.substr(std::string("https://").length());
+ }
+ host = temp_url.substr(0, temp_url.find("/"));
+ if(temp_url.find("/") != std::string::npos) {
+ resource = temp_url.substr(temp_url.find("/"));
+ }
+ if(host.find(":") != std::string::npos) {
+ std::string portstr = url.substr(host.find(":"));
port = atoi(portstr.c_str());
- hostname = hostname.substr(0, hostname.find(":"));
+ host = host.substr(0, host.find(":"));
}
+}
- RefPtr<Address> requestAddress = new Address();
+void HttpUserAgent::buildRequest(const std::string host, const std::string resource, const int port,
+ const std::string mode, RefPtr<Request> request, std::string &requestText,
+ RefPtr<Address> address) {
- std::stringstream request;
+ std::stringstream req;
if(m_proxyHost.empty()) {
- request << "GET " << resource << " HTTP/1.1\r\n";
- request << "Host: " << hostname << "\r\n";
- requestAddress->setHostName(hostname);
- requestAddress->setPort(port);
+ req << mode << " " << resource << " HTTP/1.1\r\n";
+ req << "Host: " << host << "\r\n";
+ address->setHostName(host);
+ address->setPort(port);
}
else {
// proxy connection
- request << "GET " << req->getUrl();
+ req << mode << " " << request->getUrl();
if(port != 80) {
- request << ":" << port;
+ req << ":" << port;
}
- request << " HTTP/1.1\r\n";
- request << "Host: " << hostname << "\r\n";
- requestAddress->setHostName(m_proxyHost);
- requestAddress->setPort(m_proxyPort);
+ req << " HTTP/1.1\r\n";
+ req << "Host: " << host << "\r\n";
+ address->setHostName(m_proxyHost);
+ address->setPort(m_proxyPort);
}
- std::list<std::string> params = req->getHeaderParamNames();
+ std::list<std::string> params = request->getHeaderParamNames();
for(std::list<string>::const_iterator param = params.begin();
param != params.end();
++param) {
- request << *param << ": " << req->getHeaderParam(*param) << "\r\n";
+ req << *param << ": " << request->getHeaderParam(*param) << "\r\n";
}
- request << "\r\n";
- socket->setPeerAddress(requestAddress);
- Tiki::Debug::printf("Request:\n%s", request.str().c_str());
- socket->open();
- if(socket->isOpen()) {
- Tiki::Debug::printf("Sending request...\n");
+ std::list<std::string> content = request->getContentPartNames();
+ if(!mode.compare("POST") && content.size() > 1) {
+ uint64 totalSize = request->getBoundaryMarker().size() + 4; // add 4 to account for --\r\n
+ for(std::list<std::string>::iterator iter = content.begin();
+ iter != content.end();
+ ++iter) {
+ RefPtr<Buffer> buf = request->getContentPart(*iter);
+ totalSize += buf->getUsedDataLen();
+ std::stringstream temp;
+ temp << "Content-Disposition: form-data: name=\"";
+ if(buf->getFieldName().size() > 0) {
+ temp << buf->getFieldName();
+ }
+ else {
+ temp << "File";
+ }
+ temp << "\"; filename=\"" << buf->getFileNameShort() << "\"\r\nContent-Type: " << buf->getContentType() << "\r\n";
+
+ // add section header size
+ totalSize += temp.str().size();
+ }
+
+ req << "Content-Length: " << totalSize << "\r\n";
+ req << "Expect: 100-continue\r\n";
+ req << "Content-Type: multipart/form-data; boundary=" << request->getBoundaryMarker() << "\r\n";
}
- else {
- Tiki::Debug::printf("connect failed\n");
- response->setResultCode(504);
- return response;
+ else if(!mode.compare("POST") && content.size() == 1) {
+ RefPtr<Buffer> buf = request->getContentPart(*content.begin());
+ req << "Content-Type: " << buf->getContentType() << "\r\n";
+ req << "Content-Length: " << buf->getUsedDataLen() << "\r\n";
}
+ req << "\r\n";
- RefPtr<Buffer> buf = new Buffer(2048);
- std::string requeststr = request.str();
- buf->setData((uint8 *)requeststr.c_str(), requeststr.size());
- socket->send(buf);
+ Tiki::Debug::printf("Request Text: %s\n", req.str().c_str());
+ requestText = req.str();
+}
+void HttpUserAgent::readResponse(RefPtr<Response> response, RefPtr<TCPSocket> socket) {
std::string status = "";
READ_ONE_LINE(status, socket)
@@ -189,7 +320,7 @@
else {
continue;
}
- sizeDecoded += (ch * pow(16.0f, size.size() - i - 1));
+ sizeDecoded += (ch * static_cast<int>(pow(16.0f, size.size() - i - 1)));
}
//Tiki::Debug::printf("chunk size: %d [%s]\n", sizeDecoded, size.c_str());
if(sizeDecoded > 0) {
@@ -236,14 +367,8 @@
Tiki::Debug::printf("Encoding is unknown\n");
}
response->addContentPart(DEFAULT_CONTENT_PART, fullBuf);
-
- return response;
}
-RefPtr<Response> HttpUserAgent::post(RefPtr<Request> req) const {
- return NULL;
-}
-
}; // namespace Http
}; // namespace Net
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|