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.net;
21 
22 static import std.file;
23 
24 /// `Network` implementation based on `ae.net`.
25 class AENetwork : Network
26 {
27 	private Data getData(string url)
28 	{
29 		Data result;
30 		bool got;
31 
32 		httpGet(url,
33 			(Data data) { result = data; got = true; },
34 			(string error) { throw new Exception(error); }
35 		);
36 
37 		socketManager.loop();
38 		assert(got);
39 		return result;
40 	}
41 
42 	override void downloadFile(string url, string target)
43 	{
44 		Data data = getData(url);
45 		std.file.write(target, data.contents);
46 	} ///
47 
48 	override void[] getFile(string url)
49 	{
50 		return getData(url).toHeap;
51 	} ///
52 
53 	override void[] post(string url, in void[] data)
54 	{
55 		Data result;
56 		bool got;
57 
58 		httpPost(url, DataVec(Data(data)), null,
59 			(Data data) { result = data; got = true; },
60 			(string error) { throw new Exception(error); }
61 		);
62 
63 		socketManager.loop();
64 		assert(got);
65 		return result.toHeap;
66 	} ///
67 
68 	override bool urlOK(string url)
69 	{
70 		bool got, result;
71 
72 		auto request = new HttpRequest;
73 		request.method = "HEAD";
74 		request.resource = url;
75 		try
76 		{
77 			.httpRequest(request,
78 				(HttpResponse response, string disconnectReason)
79 				{
80 					got = true;
81 					if (!response)
82 						result = false;
83 					else
84 						result = response.status == HttpStatusCode.OK;
85 				} ///
86 			);
87 
88 			socketManager.loop();
89 		} ///
90 		catch (Exception e)
91 			return false;
92 
93 		assert(got);
94 		return result;
95 	} ///
96 
97 	override string resolveRedirect(string url)
98 	{
99 		string result; bool got;
100 
101 		auto request = new HttpRequest;
102 		request.method = "HEAD";
103 		request.resource = url;
104 		.httpRequest(request,
105 			(HttpResponse response, string disconnectReason)
106 			{
107 				if (!response)
108 					throw new Exception(disconnectReason);
109 				else
110 				{
111 					got = true;
112 					result = response.headers.get("Location", null);
113 					if (result)
114 						result = url.applyRelativeURL(result);
115 				} ///
116 			} ///
117 		);
118 
119 		socketManager.loop();
120 		assert(got);
121 		return result;
122 	} ///
123 
124 	override HttpResponse httpRequest(HttpRequest request)
125 	{
126 		HttpResponse result;
127 
128 		.httpRequest(request,
129 			(HttpResponse response, string disconnectReason)
130 			{
131 				if (!response)
132 					throw new Exception(disconnectReason);
133 				else
134 					result = response;
135 			} ///
136 		);
137 
138 		socketManager.loop();
139 		assert(result);
140 		return result;
141 	} ///
142 }
143 
144 static this()
145 {
146 	net = new AENetwork();
147 }