Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
MultiGetResource.cs
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Text;
5using System.Threading.Tasks;
10using Waher.Script;
11using Waher.Security;
12
14{
19 {
20 private readonly XmppClient client;
21 private readonly HttpServer webServer;
22 private readonly string userVariable;
23 private readonly string[] userPrivileges;
24
33 public MultiGetResource(string ResourceName, XmppClient Client, HttpServer WebServer, string UserVariable,
34 params string[] UserPrivileges)
35 : base(ResourceName)
36 {
37 this.client = Client;
38 this.webServer = WebServer;
39 this.userVariable = UserVariable;
40 this.userPrivileges = UserPrivileges;
41 }
42
46 public override bool HandlesSubPaths => false;
47
51 public override bool UserSessions => false;
52
56 public bool AllowsPOST => true;
57
64 public async Task POST(HttpRequest Request, HttpResponse Response)
65 {
66 string s = Request.RemoteEndPoint;
67 int i = s.IndexOf('/');
68 if (i > 0)
69 s = s.Substring(0, i);
70
71 RosterItem Item = this.client[s];
72 bool Forbidden = false;
73
74 if (Item is null)
75 {
76 string HttpSessionID = GetSessionId(Request, Response);
77
78 if (string.IsNullOrEmpty(HttpSessionID))
79 Forbidden = true;
80 else
81 {
82 Variables Session = this.webServer.GetSession(HttpSessionID, false);
83 if (Session is null ||
84 !Session.TryGetVariable(this.userVariable, out Variable v) ||
85 !(v.ValueObject is IUser User))
86 {
87 Forbidden = true;
88 }
89 else
90 {
91 foreach (string Privilege in this.userPrivileges)
92 {
93 if (!User.HasPrivilege(Privilege))
94 {
95 Forbidden = true;
96 break;
97 }
98 }
99 }
100 }
101 }
102 else
103 {
104 if (Item.State != SubscriptionState.Both && Item.State != SubscriptionState.From)
105 Forbidden = true;
106 }
107
108 if (Forbidden)
109 throw new ForbiddenException("Access to resources not granted.");
110
111 if (!Request.HasData)
112 throw new BadRequestException("No data.");
113
114 object Data = await Request.DecodeDataAsync();
115
116 if (!(Data is string[][] Records) || !this.HasColumns(Records, 2))
117 throw new UnsupportedMediaTypeException("Data must be encoded as text/csv, each record two columns, first=resource, second=Accept header.");
118
119 HttpFieldAccept Accept = Request.Header.Accept;
120 if (!(Accept is null) && !Accept.IsAcceptable("multipart/mixed"))
121 throw new NotAcceptableException();
122
123 this.Process(Request, Response, Records);
124 }
125
126 private bool HasColumns(string[][] Records, int Nr)
127 {
128 foreach (string[] Record in Records)
129 {
130 if (Record.Length != Nr)
131 return false;
132 }
133
134 return true;
135 }
136
137 private async void Process(HttpRequest Request, HttpResponse Response, string[][] Records)
138 {
139 try
140 {
141 Uri OrgUri = new Uri(Request.Header.GetURL(false, false));
142 List<EmbeddedContent> Items = new List<EmbeddedContent>();
143 StringBuilder Header = new StringBuilder();
144 HttpRequestHeader H = Request.Header;
145
146 foreach (string[] Record in Records)
147 {
148 try
149 {
150 if (!Uri.TryCreate(OrgUri, Record[0], out Uri ItemUri))
151 throw new BadRequestException("Invalid URI: " + Record[0]);
152
153 if (ItemUri.Scheme != OrgUri.Scheme || ItemUri.Authority != OrgUri.Authority)
154 throw new ForbiddenException("Cross-domain requests not permitted.");
155
157 {
158 throw new ServiceUnavailableException("Service is shutting down. Please try again later.",
159 new KeyValuePair<string, string>("Retry-After", "300"));
160 }
161
162 if (!this.webServer.TryGetResource(ItemUri.LocalPath, out HttpResource Resource, out string SubPath) ||
163 !(Resource is IHttpGetMethod GetMethod))
164 {
165 throw new NotFoundException("Resource not found.");
166 }
167
168 using (MemoryStream ms = new MemoryStream())
169 {
170 StringBuilder sb = new StringBuilder();
171 HttpFieldReferer Referer = Request.Header.Referer;
172 HttpFieldHost Host = Request.Header.Host;
173
174 sb.Append("GET ");
175 sb.Append(ItemUri.PathAndQuery);
176 sb.AppendLine(" HTTP/1.1");
177
178 if (!(Host is null))
179 {
180 sb.Append("Host: ");
181 sb.AppendLine(Host.Value);
182 }
183
184 if (!(Referer is null))
185 {
186 sb.Append("Referer: ");
187 sb.AppendLine(Referer.Value);
188 }
189
190 sb.Append("Accept: ");
191 sb.AppendLine(Record[1]);
192
193 HttpRequest Request2 = new HttpRequest(this.webServer, new HttpRequestHeader(sb.ToString(),
194 this.webServer.VanityResources, ItemUri.Scheme), null, Request.RemoteEndPoint, Request.LocalEndPoint)
195 {
196 Session = Request.Session,
197 SubPath = SubPath,
198 Resource = Resource
199 };
200
202 HttpResponse Response2 = new HttpResponse(InternalTransfer, this.webServer, Request2);
203
204 this.webServer.RequestReceived(Request2, Request.RemoteEndPoint, Resource, SubPath);
205 await GetMethod.GET(Request2, Response2);
206
207 await InternalTransfer.WaitUntilSent(10000);
208
209 byte[] Bin = ms.ToArray();
210
211 Items.Add(new EmbeddedContent()
212 {
213 ContentType = Response2.ContentType,
214 Size = Bin.Length,
215 Raw = Encoding.ASCII.GetBytes(Convert.ToBase64String(Bin)),
216 TransferEncoding = "base64",
217 Description = Response2.StatusCode.ToString()
218 });
219 }
220 }
221 catch (HttpException ex)
222 {
223 byte[] Bin = Encoding.UTF8.GetBytes(ex.Message);
224 Items.Add(new EmbeddedContent()
225 {
226 ContentType = "text/plain; charset=utf-8",
227 Size = Bin.Length,
228 Raw = Encoding.ASCII.GetBytes(Convert.ToBase64String(Bin)),
229 TransferEncoding = "base64",
230 Description = ex.StatusCode.ToString()
231 });
232 }
233 catch (Exception ex)
234 {
235 byte[] Bin = Encoding.UTF8.GetBytes(ex.Message);
236 Items.Add(new EmbeddedContent()
237 {
238 ContentType = "text/plain; charset=utf-8",
239 Size = Bin.Length,
240 Raw = Encoding.ASCII.GetBytes(Convert.ToBase64String(Bin)),
241 TransferEncoding = "base64",
242 Description = "500"
243 });
244 }
245 }
246
247 await Response.Return(new MixedContent(Items.ToArray()));
248 }
249 catch (Exception ex)
250 {
251 await Response.SendResponse(ex);
252 }
253 }
254
255 }
256}
Represents content embedded in other content.
Represents mixed content, encoded with multipart/mixed
Definition: MixedContent.cs:7
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
The server understood the request, but is refusing to fulfill it. Authorization will not help and the...
Accept HTTP Field header. (RFC 2616, §14.1)
bool IsAcceptable(string Alternative)
Checks if an alternative is acceptable to the client sending a request.
Host HTTP Field header. (RFC 2616, §14.23)
Definition: HttpFieldHost.cs:7
Referer HTTP Field header. (RFC 2616, §14.36)
Base class for all asynchronous HTTP resources. An asynchronous resource responds outside of the meth...
Base class of all HTTP Exceptions.
string Value
HTTP Field Value
Definition: HttpField.cs:31
Contains information about all fields in an HTTP request header.
HttpFieldReferer Referer
Referer HTTP Field header. (RFC 2616, §14.36)
HttpFieldHost Host
Host HTTP Field header. (RFC 2616, §14.23)
HttpFieldAccept Accept
Accept HTTP Field header. (RFC 2616, §14.1)
string GetURL()
Gets an absolute URL for the request.
Represents an HTTP request.
Definition: HttpRequest.cs:18
HttpRequestHeader Header
Request header.
Definition: HttpRequest.cs:134
string RemoteEndPoint
Remote end-point.
Definition: HttpRequest.cs:195
bool HasData
If the request has data.
Definition: HttpRequest.cs:74
Variables Session
Contains session states, if the resource requires sessions, or null otherwise.
Definition: HttpRequest.cs:164
string LocalEndPoint
Local end-point.
Definition: HttpRequest.cs:200
async Task< object > DecodeDataAsync()
Decodes data sent in request.
Definition: HttpRequest.cs:95
Base class for all HTTP resources.
Definition: HttpResource.cs:23
static string GetSessionId(HttpRequest Request, HttpResponse Response)
Gets the session ID used for a request.
const string HttpSessionID
The Cookie Key for HTTP Session Identifiers: "HttpSessionID"
Definition: HttpResource.cs:27
string ResourceName
Name of resource.
Represets a response of an HTTP client request.
Definition: HttpResponse.cs:21
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
string ContentType
The Content-Type entity-header field indicates the media type of the entity-body sent to the recipien...
int StatusCode
HTTP Status code.
async Task Return(object Object)
Returns an object to the client. This method can only be called once per response,...
Implements an HTTP server.
Definition: HttpServer.cs:36
The resource identified by the request is only capable of generating response entities which have con...
The server has not found anything matching the Request-URI. No indication is given of whether the con...
The server is currently unable to handle the request due to a temporary overloading or maintenance of...
Base class for all transfer encodings.
Transfer encoding for internal transfers of content
Task WaitUntilSent(int TimeoutMilliseconds)
Waits for all of the data to be returned.
The server is refusing to service the request because the entity of the request is in a format not su...
Module that controls the life cycle of communication.
static bool Stopping
If the system is stopping.
Allows a client to get multiple resources in one call
override bool HandlesSubPaths
If the resource handles sub-paths.
MultiGetResource(string ResourceName, XmppClient Client, HttpServer WebServer, string UserVariable, params string[] UserPrivileges)
Allows a client to get multiple resources in one call
override bool UserSessions
If the resource uses user sessions.
async Task POST(HttpRequest Request, HttpResponse Response)
Executes the POST method on the resource.
Maintains information about an item in the roster.
Definition: RosterItem.cs:75
SubscriptionState State
roup Current subscription state.
Definition: RosterItem.cs:268
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
Definition: XmppClient.cs:59
Contains information about a variable.
Definition: Variable.cs:10
Collection of variables.
Definition: Variables.cs:25
virtual bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
Definition: Variables.cs:52
GET Interface for HTTP resources.
POST Interface for HTTP resources.
Basic interface for a user.
Definition: IUser.cs:7
SubscriptionState
State of a presence subscription.
Definition: RosterItem.cs:16
ContentType
DTLS Record content type.
Definition: Enumerations.cs:11