Implement HTTP protocol get, post, and file upload functions--design and modules

Source: Internet
Author: User
Tags rewind

I've written before, "using the WinHTTP interface for HTTP protocol get, post, and file Upload," which describes how to use the WinHTTP interface to implement HTTP GET, post, and file upload capabilities. I later found out that a lot of people were concerned about the implementation of the technology, so I decided to redesign the framework, comb the knowledge and provide a solution to test. The series will also act as part of the network module in the VC development Windows client software Tour.

This series no longer restricts technology to the WinHTTP interface, but also introduces the Curllib library. At the same time, in order to be fair and convenient to test the correctness of the code, we will introduce mature technical solutions to test.

Test environment

Use Python to build an HTTP server to detect get and post requests.

Use HFS (HTTP file server) to build an HTTP server to detect file uploads.

Use Curl as a tool for sending get, post, and file uploads.

HFS and curl are easier to get, so we just need to download the available binaries on the official web.

HFS Configuration

For example, add a live directory (real Floder) to the server. Then set the permissions for the directory to anyone.

Python Configuration and scripting

We chose the Webpy Library as the framework (Python uses 2.7). The installation method is described in HTTP://WEBPY.ORG/INSTALL.ZH-CN. We then provide the following script to print the input data

Import Weburls = (    '/get ', ' get_class ',    '/post ', ' Post_class ',) # deal get Requestclass get_class:    def get ( Self):        request_data = web.input ()        print request_data        return "hello,world!"    #deal post Requestclass post_class:       def post (self):        request_data = web.input ()        print Request_data        data = Web.data ()        print data        return "hello,world!"        if __name__ = = ' __main__ ':    app = web.application (URLs, Globals ())    App.run ()
Send test data upload file to HFS service
Curl-f "Action=upload"-F "[Email Protected]:/vcredist_x86.log" HTTP://192.168.191.1:8000/12

This way, curl uploads the file to the server.

Send a GET request
Curl "HTTP://127.0.0.1:8080/GET?K1=V1"
Python Print
<storage {' K1 ': U ' v1 '}>
Send a POST request
Curl-d "Key1=value1&key2=value2" "Http://127.0.0.1:8080/post?k1=v1"
Python Print
<storage {' Key2 ': U ' value2 ', ' K1 ': U ' v1 ', ' key1 ': U ' value1 '}>key1=value1&key2=value2127.0.0.1:44834--[26/ may/2015 19:56:22] "http/1.1 post/post"-OK
With the request and information above, we will check the validity of our code against the code we have written later.
The word "Download" of the framework design will be the source of my design for the framework. "Down" is the transfer of data from one side, "load" is the data sent to the local save. How to "under", How to "download" is optional. So I have defined two virtual classes--toolsinterface::ihttprequest and Toolsinterface::imemfileoperation respectively for these two behaviors. "Down", we can use the WinHTTP interface or the Curl interface. "Download", we can choose to save in memory or save to disk. And then these two separate behaviors, I'm using a bonding class--toolsinterface::csetoperation to make these two behaviors correlate and decouple.

is the entire frame diagram. It completely reflects the relationships of each class. We will then expand and explain it in conjunction with this diagram.

First, let's look at the "Down" interface function definition

Class Ihttprequest{public:ihttprequest () {};virtual ~ihttprequest () {};p ublic:virtual void Start () = 0;virtual void Stop () = 0;virtual bool Issuc () = 0;virtual void SetUrl (const std::wstring& wstrurl) = 0;virtual void SetParams (const CPAR am& Param) = 0;virtual void setagent (const std::wstring& wstragent) = 0;virtual void Appendheader (const LISTWSTR&A mp listheaders) = 0;virtual void SetTimeOut (int nresolvetimeout,int nconnecttimeout,int nsendtimeout,int nreceivetimeout) = 0;                        virtual void setfinishevent (HANDLE hfinish) = 0;void setprocesscallback (lpcallback fprocess) {m_callback = fprocess;}; Protected:toolsinterface::lpcallback M_callback;};
The function of the class is named more directly, and it should be possible to guess the meaning from its name. Here is the SetParams method, which provides support for Get, post, and upload protocols at the same time. But its implementation in different protocols is not the same.
Let's look at the interface definitions provided by "download"

Class Imemfileoperation {public:imemfileoperation () {};virtual ~imemfileoperation () {};p ublic://void Clearerr (FILE * Stream)//resets both the error and the EOF indicators of the stream./* when a I/O function fails either because of an ER Ror or because the end of the file has been reached, and one of the these internal indicators may be set for the stream. The state of these indicators was cleared by a call to this function, or by a call to any of:rewind, fseek, Fsetpos and FR eopen.*/virtual void Mfclearerr () {};//int fclose (FILE * stream);//Closes the FILE associated with the stream and dis Associates It./*all internal buffers associated with the stream is disassociated from it and flushed:the content of any Unwritten output buffer is written and the content of any unread input buffer is discarded. Even if the call fails, the stream passed as parameter would no longer be associated with the file nor its Buffers.*/virtua l bool Mfclose () = 0;//int feof (FILE * stream);//Checks whether The end-of-file indicator associated with stream are set, returning a value different from zero if it is./*this indicator is generally set by a previous operation on the stream that attempted to read at or past the end-of-file. Notice that stream ' s internal position indicator could point to the end-of-file for the next operation, but still, the End-o F-file indicator May is not set until a operation attempts to read at the point. This indicator was cleared by a call to Clearerr, rewind, fseek, Fsetpos or Freopen. Although if the position indicator is not repositioned by such a call, the next I/O operation is likely to set the Indicat  or again.*/virtual int mfeof () = 0;//int ferror (FILE * stream);//Checks If the error indicator associated with stream is set, returning a value different from zero if it is./*this indicator are generally set by a previous operation on the S Tream that failed, and was cleared by a call to Clearerr, rewind or freopen.*/virtual int mferror () {return 0;};/ /int FFlush (FILE * stream);//flush stream/*if The given stream is open for writing (or If it is open for updating and the Last I/O operation was a output operation) any unwritten data in it output buffer is written to the file. If stream is a null pointer, all such streams is flushed. In all other cases, the behavior depends on the specific library implementation. In some implementations, flushing a stream open for reading causes it input buffer to be cleared (it is not portabl e expected behavior). The stream remains open after this call. When a file was closed, either because of a call to Fclose or because the program terminates, all the buffers associated WI Th it is automatically flushed.*/virtual int mfflush () {return 0;};/ /int fgetc (file * stream);//Get character from Stream/*returns the character currently pointed by the internal FILE p Osition indicator of the specified stream. The internal file position indicator is then advanced to the next character. If the stream is at the End-of-file when called, the function returns EOF and sets the End-of-file indicator for the stream (feof). If A read error occurs, the function returns EOF and sets the error indicator for the stream (ferror). Fgetc and Getc is E Quivalent, except that GETC is implemented as a macro in some libraries.*/virtual int mfgetc () = 0;//int Fgetpos (FI  LE * Stream, fpos_t * pos);//retrieves the current position in the Stream./*the function fills the Fpos_t object pointed By POS with the information needed from the stream's position indicator to restore the stream to their current position (an D multibyte state, if wide-oriented) with a call to Fsetpos. The Ftell function can be used to retrieve the current position in the stream as an integer value.*/virtual int mfgetpos (  fpos_t * pos) = 0;//char * fgets (char * str, int num, FILE * stream);//Get string from stream/*reads characters from Stream and stores them as a C string into str until (NUM-1) characters has been read or eitheR a newline or the end-of-file is reached, whichever happens first. A newline character makes fgets stop reading, but it's considered a valid character by the function and included in the S Tring copied to Str. A terminating null character is automatically appended after the characters copied to Str. Notice that Fgets was quite different from Gets:not only fgets accepts a stream argument, but also allows to specify the M Aximum size of STR and includes in the string any ending newline character.*/virtual char * mfgets (char * str, int num) = 0;//File * fopen (const char * filename, const char * mode);//Open File/*opens The file whose name is specified in t He parameter filename and associates it with a stream that can is identified in the future operations by the FILE pointer Retu rned. The operations that is allowed on the stream and how these is performed is defined by the mode parameter. The returned stream is fully buffered by default if it's known to not refer to an interactive DevicE (see SETBUF). The returned pointer can be disassociated from the file by calling Fclose or Freopen. All opened files is automatically closed on the normal program termination. The running environment supports at least FOPEN_MAX files open simultaneously.*/virtual bool Mfopen () = 0;//int FPUTC (i NT character, FILE * stream);//writes a character to the stream and advances the position indicator./*the character is W  Ritten at the position indicated by the internal position indicator of the stream, which are then automatically one.*/virtual int MFPUTC (int character) = 0;//int fputs (const char * str, FILE * stream);//Writes the C string poi Nted by STR-the Stream./*the function begins copying from the address specified (str) until it reaches the terminating Null character (' + '). This terminating null-character isn't copied to the stream. Notice that fputs not only differs from puts on that the destination stream can is specified, but also fputs does not writ E Additional Characters, while puts appends a newline character at the end automatically.*/virtual int mfputs (const char * str) = 0;  size_t fread (void * ptr, size_t size, size_t count, FILE * stream);//Read block of data from Stream/*reads an array of Count elements, each one with a size of size bytes, from the stream and stores them in the block of memory specified B Y ptr. The position indicator of the stream is advanced by the total amount of bytes read. The total amount of bytes read if successful is (Size*count). */virtual size_t mfread (void * ptr, size_t size, size_t count ) = 0;//int fseek (FILE * stream, long int offset, int origin);//sets the position indicator associated with the Strea M to a new position./*for streams open in binary mode, the new position was defined by adding offset to a reference positio n specified by origin. For streams open in text mode, offset shall either is zero or a value returned by a previous call to Ftell, and Origin Sha ll necessarily be seek_set. If the FUnction is called with other values for these arguments, support depends on the particular system and library Implementati On (non-portable).  The End-of-file internal indicator of the stream is cleared after a successful call to this function, and all effects from Previous calls to ungetc on the this stream is dropped. On streams open for Update (read+write), a call to Fseek allows to switch between reading and writing.*/virtual int Mfseek (long offset, int origin) = 0;//int Fsetpos (FILE * stream, const fpos_t * pos);//Restores the current position in T He stream to pos./*the internal file position indicator associated with stream are set to the position represented by POS, Which is a pointer to an fpos_t object whose value shall has been previously obtained by a call to Fgetpos.  The End-of-file internal indicator of the stream is cleared after a successful call to this function, and all effects from Previous calls to ungetc on the this stream is dropped. On streams open for update (READ+WRITE), a call to Fsetpos allows to switch between reading and writing. A similar function, fseek, can be used to set arbitrary positions on streams open in binary mode.*/virtual int Mfsetpos (c Onst fpos_t * pos) = 0;//long int ftell (FILE * stream);//Returns The current value of the position indicator of the Stream./*for binary streams, this is the number of bytes from the beginning of the file. For text streams, the numerical value is not being meaningful but can still is used to restore the position to the same posi tion later using fseek (if there be characters put back using ungetc still pending of being in read, the behavior is Undefin ed). */virtual long Mftell () = 0;//size_t fwrite (const void * ptr, size_t size, size_t count, FILE * stream);//Write B Lock of data to stream/*writes an array of count elements, each one with a size of size bytes, from the block of memory PO Inted by PTR to the current position in the stream. The position indicator of the stream is advanced by the Number of bytes written. Internally, the function interprets the block pointed by PTR as if it is an array of (Size*count) elements of type unsign Ed Char, and writes them sequentially to stream as if FPUTC is called for each byte.*/virtual size_t mfwrite (const void * ptr, size_t size, size_t count) = 0;//void Rewind (FILE * stream);//sets the position indicator associated with STR EAM to the beginning of the file./*the End-of-file and error internal indicators associated to the stream is cleared Afte R A successful call to the This function, and all effects from previous calls to ungetc the this stream is dropped. On streams open for Update (read+write), a call to rewind allows to switch between reading and writing.*/virtual void Mfre Wind () = 0;/* unsuportint putc (int character, FILE * stream); Use Mfputcint getc (FILE * stream); Use Mfgetcfile * freopen (const char * filename, const char * mode, file * stream); void setbuf (File * stream, char * b uffer); int setvbuf (FILE *Stream, char * buffer, int mode, size_t size); int fprintf (FILE * stream, const char * format, ...); int fscanf (FILE * stream, const char * format, ...);  int ungetc (int character, file * stream), int vfprintf (file * stream, const char * format, va_list arg); int vfscanf ( FILE * Stream, const char * format, va_list arg); */};
This set of interfaces is defined in a way that refers to the operation of a file. Because either memory or disk, they are a medium for storing data. File as a way of storing disk media, which provides a complete definition of how to operate. So we can assume that the file operation covers the memory operation. So we use the file operation method to define the operation interface.
Finally, we'll look at the bonding class.

Class Csetoperation{public:csetoperation () {m_pfmop = NULL;}; Virtual ~csetoperation () {};p ublic:        void Open () {            if (m_pfmop) {                m_pfmop->mfopen ()}        }        void Close () {            if (m_pfmop) {                m_pfmop->mfclose ();            }        }        size_t Write (const void * ptr, size_t size, size_t count) {            if (m_pfmop) {                return m_pfmop->mfwrite (PTR, siz E, count);            }            return 0;        } void Setoperation (imemfileoperation* pfmop) {m_pfmop = Pfmop;};    private:imemfileoperation* M_pfmop;};
Each class that implements the Ihttprequest interface obtains the ability to "load" by inheriting the class. Its implementation is also simple-just a simple forwarding, through this layer of class, we will "down" and "load" to understand the decoupling.

Example

Let's take an example of a GET request that uses the WinHTTP interface and memory Save method

httprequestfm::chttptransbypost* p = new Httprequestfm::chttptransbypost (); toolsinterface::imemfileoperation* pmemop = new Memfileoperation::cmemoperation ();p->setoperation (pMemOp);p- >setprocesscallback (Procsscallback); Toolsinterface::cparam Param; Param.add (L "Name1", L "Value1"); Param.add (L "Name2", L "Value2");p->setparams (Param);p->seturl (bigfileurl);p->start ();d elete Pmemop; Pmemop = Null;delete p;p = NULL;

Although we are saving data in memory form, we can still access it as if it were a file. If you insert the following code before the delete pmemop

        file* file = fopen ("F:/11.rar", "wb+");        Pmemop->mfopen ();        while (!pmemop->mfeof ()) {            char c = (char) pmemop->mfgetc ();            Fwrite (&c,1,1, file);        }        fclose (file);        Pmemop->mfclose ();        file* file1 = fopen ("F:/111.rar", "wb+");        Pmemop->mfopen ();        while (!pmemop->mfeof ()) {            char buffer[1024] = {0};            size_t size = pmemop->mfread (buffer, 1, 1024x768);            Fwrite (Buffer,1,size, file1);        }        Fclose (file1);        Pmemop->mfclose ();
Because this series is to explain the use of different ways to implement HTTP various requests, so "download" the specific implementation is not discussed. I will give it in the source code of the project later.

Implement HTTP protocol get, post, and file upload functions--design and modules

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.