1 /** 2 Convenience functions for working with web forms. 3 4 Copyright: © 2012-2015 Sönke Ludwig 5 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 6 Authors: Sönke Ludwig, Jan Krüger 7 */ 8 deprecated("Use vibe.inet.webform instead") 9 module vibe.http.form; 10 11 public import vibe.inet.webform; 12 13 import vibe.http.client : HTTPClientRequest; // for writeFormBody 14 import vibe.http.server; 15 16 import std.array; 17 import std.conv; 18 import std.range; 19 import std..string; 20 import std.typecons : isTuple; 21 22 23 /** 24 Encodes the given dictionary as URL encoded form data. 25 */ 26 void writeFormData(R)(R dst, in string[string] data) 27 if (isOutputRange!(R, char)) 28 { 29 import vibe.textfilter.urlencode; 30 31 bool first = true; 32 foreach (k, v; data) { 33 if (first) first = false; 34 else dst.put("&"); 35 filterURLEncode(dst, k); 36 dst.put("="); 37 filterURLEncode(dst, v); 38 } 39 } 40 41 /// 42 unittest { 43 import std.array; 44 import vibe.core.log; 45 import vibe.http.form; 46 47 void test() 48 { 49 auto dst = appender!string(); 50 dst.writeFormData(["field1": "value1", "field2": "value2"]); 51 logInfo("Form data: %s", dst.data); 52 } 53 } 54 55 /** 56 Encodes the given ranges of `Tuple!(string, string)` as URL encoded form data 57 */ 58 void writeFormData(R, PairRange)(R dst, PairRange pr) 59 if (isOutputRange!(R, char) && isTuple!(ElementType!PairRange) && ElementType!PairRange.length == 2) 60 { 61 import vibe.textfilter.urlencode; 62 63 if(pr.empty) return; 64 65 auto fst = pr.front; 66 pr.popFront(); 67 68 filterURLEncode(dst, fst[0]); 69 dst.put("="); 70 filterURLEncode(dst, fst[1]); 71 72 foreach (pair; pr) { 73 dst.put("&"); 74 filterURLEncode(dst, pair[0]); 75 dst.put("="); 76 filterURLEncode(dst, pair[1]); 77 } 78 } 79 80 /** 81 Writes a `vibe.http.client.HTTPClientRequest` body as URL encoded form data. 82 */ 83 void writeFormBody(HTTPClientRequest req, in string[string] form) 84 { 85 import vibe.http.form; 86 import vibe.stream.wrapper; 87 88 StringLengthCountingRange len; 89 writeFormData(&len, form); 90 req.contentType = "application/x-www-form-urlencoded"; 91 req.contentLength = len.count; 92 auto rng = streamOutputRange(req.bodyWriter); 93 writeFormData(&rng, form); 94 } 95 96 /// 97 unittest { 98 import vibe.core.log; 99 import vibe.http.client; 100 import vibe.http.form; 101 import vibe.stream.operations; 102 103 void sendForm() 104 { 105 requestHTTP("http://example.com/form", 106 (scope req) { 107 req.method = HTTPMethod.POST; 108 req.writeFormBody(["field1": "value1", "field2": "value2"]); 109 }, 110 (scope res) { 111 logInfo("Response: %s", res.bodyReader.readAllUTF8()); 112 }); 113 } 114 } 115 116 /** 117 Writes a `vibe.http.client.HTTPClientRequest` body as URL encoded form data. 118 119 Params: 120 req = Request object to write to. 121 form = range of `t = Tuple!(string, string)`, 122 where `t[0]` is the name and `t[1]` the 123 value of a form entry. 124 */ 125 void writeFormBody(PairRange)(HTTPClientRequest req, PairRange form) 126 if(isTuple!(ElementType!PairRange) && ElementType!PairRange.length == 2) 127 { 128 import vibe.http.form; 129 import vibe.stream.wrapper; 130 131 StringLengthCountingRange len; 132 writeFormData(&len, form.save); 133 req.contentType = "application/x-www-form-urlencoded"; 134 req.contentLength = len.count; 135 auto rng = streamOutputRange(req.bodyWriter); 136 writeFormData(&rng, form); 137 } 138 139 /// 140 unittest { 141 import vibe.core.log; 142 import vibe.http.client; 143 import vibe.http.form; 144 import vibe.stream.operations; 145 import std.range; 146 147 void sendForm() 148 { 149 string[] names = ["foo", "bar", "baz"]; 150 string[] values = ["1", "2", "3"]; 151 auto form = zip(names, values); 152 requestHTTP("http://example.com/form", 153 (scope req) { 154 req.method = HTTPMethod.POST; 155 req.writeFormBody(form); 156 }, 157 (scope res) { 158 logInfo("Response: %s", res.bodyReader.readAllUTF8()); 159 }); 160 } 161 } 162 163 164 /// private 165 struct StringLengthCountingRange { 166 import std.utf; 167 size_t count = 0; 168 void put(string str) { count += str.length; } 169 void put(dchar ch) { count += codeLength!char(ch); } 170 }