1 /**
2  * ae.sys.net implementation using ae.net
3  * Note: ae.net requires an SSL provider for HTTPS links.
4  *
5  * License:
6  *   This Source Code Form is subject to the terms of
7  *   the Mozilla Public License, v. 2.0. If a copy of
8  *   the MPL was not distributed with this file, You
9  *   can obtain one at http://mozilla.org/MPL/2.0/.
10  *
11  * Authors:
12  *   Vladimir Panteleev <ae@cy.md>
13  */
14 
15 module ae.sys.net.ae;
16 
17 import ae.net.asockets;
18 import ae.net.http.client;
19 import ae.net.ietf.url;
20 import ae.sys.dataset : DataVec;
21 import ae.sys.net;
22 
23 static import std.file;
24 
25 /// `Network` implementation based on `ae.net`.
26 class AENetwork : Network
27 {
28 	private Data getData(string url)
29 	{
30 		Data result;
31 		bool got;
32 
33 		httpGet(url,
34 			(Data data) { result = data; got = true; },
35 			(string error) { throw new Exception(error); }
36 		);
37 
38 		socketManager.loop();
39 		assert(got);
40 		return result;
41 	}
42 
43 	override void downloadFile(string url, string target)
44 	{
45 		Data data = getData(url);
46 		data.enter((contents) {
47 			std.file.write(target, contents);
48 		});
49 	} ///
50 
51 	override ubyte[] getFile(string url)
52 	{
53 		return getData(url).toGC();
54 	} ///
55 
56 	override ubyte[] post(string url, const(ubyte)[] data)
57 	{
58 		Data result;
59 		bool got;
60 
61 		httpPost(url, DataVec(Data(data)), null,
62 			(Data data) { result = data; got = true; },
63 			(string error) { throw new Exception(error); }
64 		);
65 
66 		socketManager.loop();
67 		assert(got);
68 		return result.toGC();
69 	} ///
70 
71 	override bool urlOK(string url)
72 	{
73 		bool got, result;
74 
75 		auto request = new HttpRequest;
76 		request.method = "HEAD";
77 		request.resource = url;
78 		try
79 		{
80 			.httpRequest(request,
81 				(HttpResponse response, string disconnectReason)
82 				{
83 					got = true;
84 					if (!response)
85 						result = false;
86 					else
87 						result = response.status == HttpStatusCode.OK;
88 				} ///
89 			);
90 
91 			socketManager.loop();
92 		} ///
93 		catch (Exception e)
94 			return false;
95 
96 		assert(got);
97 		return result;
98 	} ///
99 
100 	override string resolveRedirect(string url)
101 	{
102 		string result; bool got;
103 
104 		auto request = new HttpRequest;
105 		request.method = "HEAD";
106 		request.resource = url;
107 		.httpRequest(request,
108 			(HttpResponse response, string disconnectReason)
109 			{
110 				if (!response)
111 					throw new Exception(disconnectReason);
112 				else
113 				{
114 					got = true;
115 					result = response.headers.get("Location", null);
116 					if (result)
117 						result = url.applyRelativeURL(result);
118 				} ///
119 			} ///
120 		);
121 
122 		socketManager.loop();
123 		assert(got);
124 		return result;
125 	} ///
126 
127 	override HttpResponse httpRequest(HttpRequest request)
128 	{
129 		HttpResponse result;
130 
131 		.httpRequest(request,
132 			(HttpResponse response, string disconnectReason)
133 			{
134 				if (!response)
135 					throw new Exception(disconnectReason);
136 				else
137 					result = response;
138 			} ///
139 		);
140 
141 		socketManager.loop();
142 		assert(result);
143 		return result;
144 	} ///
145 }
146 
147 static this()
148 {
149 	net = new AENetwork();
150 }