Merge pull request #344 from RangelReale/htmlformcontentlength

HTMLForm Content-Length calculation
This commit is contained in:
Aleksandar Fabijanic
2014-05-21 22:27:12 -05:00
12 changed files with 164 additions and 5 deletions

View File

@@ -16,6 +16,7 @@
#include "Poco/Net/FilePartSource.h"
#include "Poco/Path.h"
#include "Poco/File.h"
#include "Poco/Exception.h"
@@ -28,7 +29,7 @@ namespace Net {
FilePartSource::FilePartSource(const std::string& path):
_istr(path)
_path(path), _istr(path)
{
Path p(path);
_filename = p.getFileName();
@@ -39,6 +40,7 @@ FilePartSource::FilePartSource(const std::string& path):
FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType):
PartSource(mediaType),
_path(path),
_istr(path)
{
Path p(path);
@@ -50,6 +52,7 @@ FilePartSource::FilePartSource(const std::string& path, const std::string& media
FilePartSource::FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType):
PartSource(mediaType),
_path(path),
_filename(filename),
_istr(path)
{
@@ -76,4 +79,11 @@ const std::string& FilePartSource::filename() const
}
std::streamsize FilePartSource::getContentLength() const
{
Poco::File p(_path);
return p.getSize();
}
} } // namespace Poco::Net

View File

@@ -27,6 +27,7 @@
#include "Poco/StreamCopier.h"
#include "Poco/URI.h"
#include "Poco/String.h"
#include "Poco/CountingStream.h"
#include <sstream>
@@ -41,8 +42,21 @@ namespace Poco {
namespace Net {
const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded";
const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded";
const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1;
class HTMLFormCountingOutputStream : public CountingOutputStream
{
public:
HTMLFormCountingOutputStream() : _isvalid(true) {}
bool getIsValid() const { return _isvalid; }
void setIsValid(bool v) { _isvalid = v; }
private:
bool _isvalid;
};
HTMLForm::HTMLForm():
@@ -217,6 +231,20 @@ void HTMLForm::prepareSubmit(HTTPRequest& request)
}
std::streamsize HTMLForm::calculateContentLength()
{
if (_boundary.empty())
throw HTMLFormException("Form must be prepared");
HTMLFormCountingOutputStream c;
write(c);
if (c.getIsValid())
return c.chars();
else
return UNKNOWN_CONTENT_LENGTH;
}
void HTMLForm::write(std::ostream& ostr, const std::string& boundary)
{
if (_encoding == ENCODING_URL)
@@ -338,6 +366,8 @@ void HTMLForm::writeUrl(std::ostream& ostr)
void HTMLForm::writeMultipart(std::ostream& ostr)
{
HTMLFormCountingOutputStream *costr(dynamic_cast<HTMLFormCountingOutputStream*>(&ostr));
MultipartWriter writer(ostr, _boundary);
for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it)
{
@@ -365,7 +395,17 @@ void HTMLForm::writeMultipart(std::ostream& ostr)
header.set("Content-Disposition", disp);
header.set("Content-Type", ita->pSource->mediaType());
writer.nextPart(header);
StreamCopier::copyStream(ita->pSource->stream(), ostr);
if (costr)
{
// count only, don't move stream position
std::streamsize partlen = ita->pSource->getContentLength();
if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH)
costr->addChars(partlen);
else
costr->setIsValid(false);
}
else
StreamCopier::copyStream(ita->pSource->stream(), ostr);
}
writer.close();
_boundary = writer.boundary();

View File

@@ -21,6 +21,9 @@ namespace Poco {
namespace Net {
const int PartSource::UNKNOWN_CONTENT_LENGTH = -1;
PartSource::PartSource():
_mediaType("application/octet-stream")
{
@@ -49,5 +52,9 @@ const std::string& PartSource::filename() const
return EMPTY;
}
std::streamsize PartSource::getContentLength() const
{
return UNKNOWN_CONTENT_LENGTH;
}
} } // namespace Poco::Net

View File

@@ -60,4 +60,10 @@ const std::string& StringPartSource::filename() const
}
std::streamsize StringPartSource::getContentLength() const
{
return _istr.str().length();
}
} } // namespace Poco::Net