1 /*******************************************************************************
2 
3         copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
4 
5         license:        BSD style: $(LICENSE)
6 
7         version:        Initial release: January 2006
8         
9         author:         Kris
10 
11 *******************************************************************************/
12 
13 module tango.net.http.HttpPost;
14 
15 public import   tango.net.Uri;
16 
17 private import  tango.io.model.IConduit;
18 
19 private import  tango.net.http.HttpClient,
20                 tango.net.http.HttpHeaders;
21 
22 /*******************************************************************************
23 
24         Supports the basic needs of a client sending POST requests to a
25         HTTP server. The following is a usage example:
26 
27         ---
28         // open a web-page for posting (see HttpGet for simple reading)
29         auto post = new HttpPost ("http://yourhost/yourpath");
30 
31         // send, retrieve and display response
32         Cout (cast(char[]) post.write("posted data", "text/plain"));
33         ---
34 
35 *******************************************************************************/
36 
37 class HttpPost : HttpClient
38 {      
39         /***********************************************************************
40         
41                 Create a client for the given URL. The argument should be
42                 fully qualified with an "http:" or "https:" scheme, or an
43                 explicit port should be provided.
44 
45         ***********************************************************************/
46 
47         this (const(char)[] url)
48         {
49                 this (new Uri(url));
50         }
51 
52         /***********************************************************************
53         
54                 Create a client with the provided Uri instance. The Uri should 
55                 be fully qualified with an "http:" or "https:" scheme, or an
56                 explicit port should be provided. 
57 
58         ***********************************************************************/
59 
60         this (Uri uri)
61         {
62                 super (HttpClient.Post, uri);
63 
64                 // enable header duplication
65                 getResponseHeaders().retain (true);
66         }
67 
68         /***********************************************************************
69         
70                 Send query params only
71 
72         ***********************************************************************/
73 
74         void[] write ()
75         {
76                 return write (null);
77         }
78 
79         /***********************************************************************
80         
81                 Send raw data via the provided pump, and no query 
82                 params. You have full control over headers and so 
83                 on via this method.
84 
85         ***********************************************************************/
86 
87         void[] write (Pump pump)
88         {
89                 auto buffer = super.open (pump);
90                 try {
91                     // check return status for validity
92                     auto status = super.getStatus();
93                     if (status is HttpResponseCode.OK || 
94                         status is HttpResponseCode.Created || 
95                         status is HttpResponseCode.Accepted)
96                         buffer.load (getResponseHeaders().getInt (HttpHeader.ContentLength));
97                     } finally {close();}
98 
99                 return buffer.slice();
100         }
101 
102         /***********************************************************************
103         
104                 Send content and no query params. The contentLength header
105                 will be set to match the provided content, and contentType
106                 set to the given type.
107 
108         ***********************************************************************/
109 
110         void[] write (const(void)[] content, const(char)[] type)
111         {
112                 auto headers = super.getRequestHeaders();
113 
114                 headers.add    (HttpHeader.ContentType, type);
115                 headers.addInt (HttpHeader.ContentLength, content.length);
116                 
117                 return write ((OutputBuffer b){b.append(content);});
118         }
119 }
120 
121 debug(HttpPost)
122 {
123      import tango.io.Console;
124 
125     void main()
126     {
127         auto page = new HttpPost("http://driv.pl/tango/index.php");
128         // Its important to set cookies below in order to parse post fields properly 
129         page.getRequestHeaders().add(HttpHeader.AcceptCharset, "UTF-8,*"); 
130         Cout("Enter your name: ").newline;
131         string name;
132         Cin.readln(name);
133         auto fields = "submit=send&nick=" ~ name;
134         Cout( cast(char[]) page.write(cast(void[]) fields, "application/x-www-form-urlencoded") )();
135     }
136 }