Browse Source

Now upload filter test is completed

master
Artyom Beilis 8 years ago
parent
commit
72a96d5de0
8 changed files with 104 additions and 10 deletions
  1. +4
    -0
      CMakeLists.txt
  2. +46
    -5
      cppcms/http_content_filter.h
  3. +10
    -0
      cppcms/http_context.h
  4. +7
    -0
      cppcms/http_file.h
  5. +5
    -0
      private/http_file_buffer.h
  6. +11
    -2
      src/http_file.cpp
  7. +6
    -0
      tests/filter_test.cpp
  8. +15
    -3
      tests/filter_test.py

+ 4
- 0
CMakeLists.txt View File

@@ -833,6 +833,10 @@ add_test(pool_test
pool_test "-c" "${CNF}/pool_test.js"
"--test-exec=${PYTHON} ${CNF}/pool_test.py")

add_test(filter_test
filter_test "-c" "${CNF}/filter_test.js"
"--test-exec=${PYTHON} ${CNF}/filter_test.py")

add_test(async_status_test
status_test "-c" "${CNF}/status_test.js" "--test-async=async"
"--test-exec=${PYTHON} ${CNF}/status_test.py async")


+ 46
- 5
cppcms/http_content_filter.h View File

@@ -30,37 +30,78 @@ namespace http {
class CPPCMS_API abort_upload : public cppcms_error {
public:
///
/// Abort
/// Abort upload progress, thrown from classes derived from basic_content_filter
/// to abort the upload progress. status_code is the HTTP error code returned, for example 413
/// requested entity is too large
///
abort_upload(int status_code);
virtual ~abort_upload() throw();

///
/// Get the code
///
int code() const;
private:
int code_;
};


///
/// Class that represent the limits on the input content sizes
///
class CPPCMS_API content_limits : public booster::noncopyable {
friend class request;
public:
/// \cond INTERNAL
content_limits(impl::cached_settings const &);
/// \endcond

content_limits();
~content_limits();
/// \endcond

///
/// Get the size limit in bytes of any non multipart/form-data content
///
/// Note form fields without content-type would be limited by this
/// size even if the multipart_form_data_limit is much larger
///
long long content_length_limit() const;
///
/// Set the size limit of any non multipart/form-data content
///
/// Note form fields without content-type would be limited by this
/// size even if the multipart_form_data_limit is much larger
///
void content_length_limit(long long size);

///
/// Get the size limit of multipart/form-data content in bytes
///
/// Note form fields without content-type would be limited by content_length_limit
/// size even if the multipart_form_data_limit is much larger
///
long long multipart_form_data_limit() const;
///
/// Set the size limit of multipart/form-data content in bytes
///
/// Note form fields without content-type would be limited by content_length_limit
/// size even if the multipart_form_data_limit is much larger
///
void multipart_form_data_limit(long long size);

///
/// Get the maximal size of file that is still hold in memory rather than disk
///
size_t file_in_memory_limit() const;
///
/// Set the maximal size of file that is still hold in memory rather than disk
///
void file_in_memory_limit(size_t size);

///
/// Get a location of a temporary directory that files are uploaded to, if empty system default is used
///
std::string uploads_path() const;
///
/// Set a location of a temporary directory that files are uploaded to, if empty system default is used
///
void uploads_path(std::string const &path);

private:


+ 10
- 0
cppcms/http_context.h View File

@@ -200,6 +200,10 @@ namespace cppcms {
booster::hold_ptr<T> p;
};
public:
///
/// Get context specific value of type T binded to context. If none is stored or
/// type mismatched NULL is returned
///
template<typename T>
T *get_specific()
{
@@ -208,6 +212,9 @@ namespace cppcms {
return 0;
return sh->p.get();
}
///
/// Reset context specific value of type T binded to context. Old value is deleted
///
template<typename T>
void reset_specific(T *ptr = 0)
{
@@ -224,6 +231,9 @@ namespace cppcms {
set_holder(sh);
}
}
///
/// Release context specific value binded to context.
///
template<typename T>
T *release_specific()
{


+ 7
- 0
cppcms/http_file.h View File

@@ -76,6 +76,13 @@ namespace http {
/// Make sure that file created by output_file member function is not removed in destructor
///
void make_permanent();
///
/// Close the file if it is still open, if the file temporary it is deleted, the the
/// file in memory its content is removed, data() would return non-usable stream
///
/// Returns 0 in case of sucess and -1 in case of failure
///
int close();
///
/// Save file to file named \a filename. Throws cppcms_error in case of failure.


+ 5
- 0
private/http_file_buffer.h View File

@@ -102,6 +102,11 @@ public:
}
f_ = 0;
}
setp(0,0);
setg(0,0,0);
clear(input_);
clear(output_);
clear(data_);
return 0;
}
#ifdef DEBUG_FILE_BUFFER


+ 11
- 2
src/http_file.cpp View File

@@ -152,14 +152,23 @@ file::file() :
{
}

file::~file()

int file::close()
{
if(!d->fb.in_memory() && !removed_) {
d->fb.close();
int r = d->fb.close();
if(file_temporary_ && !d->fb.name().empty()) {
booster::nowide::remove(d->fb.name().c_str());
}
return r;
}
else
return d->fb.close();
}

file::~file()
{
close();
}

void file::filename(std::string const &v)


+ 6
- 0
tests/filter_test.cpp View File

@@ -168,6 +168,11 @@ public:
if(request().get("abort")=="on_headers_ready")
do_abort(501);
request().set_content_filter(*this);
std::string cl_limit,mp_limit;
if((cl_limit=request().get("cl_limit"))!="")
request().limits().content_length_limit(atoi(cl_limit.c_str()));
if((mp_limit=request().get("mp_limit"))!="")
request().limits().multipart_form_data_limit(atoi(mp_limit.c_str()));
}
else {
test_data *td = context().get_specific<test_data>();
@@ -193,6 +198,7 @@ public:
}
};


int main(int argc,char **argv)
{
try {


+ 15
- 3
tests/filter_test.py View File

@@ -31,9 +31,12 @@ def make_multipart_form_data(qs):
r=[]
fc={}
ln={}
post={}
for item in qs:
key=item.split('=')[0]
value = item.split('=')[1]
if key=='formdata':
post[value]=True
pr=key[0:2]
if pr == 'f_' or pr == 'l_':
name = key[2:]
@@ -46,7 +49,8 @@ def make_multipart_form_data(qs):
l=ln[name]
c=fc[name]
r.append('--123456\r\n')
r.append('Content-Type: text/plain\r\n')
if not name in post:
r.append('Content-Type: text/plain\r\n')
r.append('Content-Disposition: form-data; name="' + name +'"\r\n\r\n')
r.append(make_content(c,l))
r.append('\r\n')
@@ -186,14 +190,22 @@ def test_upload():
test(r['status']==400)
test_on_error_called()
r=transfer('/upload',['l_1=100','f_1=a','save_to_1=test.txt'])
test(r['status']==200)
try:
os.remove('test.txt')
except:
pass
r=transfer('/upload',['l_1=100','f_1=a','save_to_1=test.txt'])
test(r['status']==200)
time.sleep(0.2);
test(open('test.txt','rb').read() == make_content('a',100))
os.remove('test.txt')

test(transfer('/upload',['l_1=100','f_1=a','cl_limit=5'])['status']==200)
test(transfer('/upload',['fail=1','cl_limit=5'],{'content':'{"x":1000}','content_type':'application/json'})['status']==413)
test(transfer('/upload',['fail=1','l_1=100','f_1=a','mp_limit=50'])['status']==413)
test(transfer('/upload',['l_1=100','f_1=a','mp_limit=200'])['status']==200)
test(transfer('/upload',['formdata=1','l_1=100','f_1=a','l_2=200','f_2=b','mp_limit=500','cl_limit=100'])['status']==200)
test(transfer('/upload',['fail=1','formdata=1','l_1=100','f_1=a','l_2=200','f_2=b','mp_limit=500','cl_limit=99'])['status']==413)

test_upload()
print "OK"

Loading…
Cancel
Save