diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/Servers/BaseHttpServer.cs | 69 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/IHttpAgentHandler.cs | 4 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/OSHttpStatusCodes.cs | 168 |
3 files changed, 220 insertions, 21 deletions
diff --git a/OpenSim/Framework/Servers/BaseHttpServer.cs b/OpenSim/Framework/Servers/BaseHttpServer.cs index a5e256b..91b5718 100644 --- a/OpenSim/Framework/Servers/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/BaseHttpServer.cs | |||
@@ -120,6 +120,10 @@ namespace OpenSim.Framework.Servers | |||
120 | return false; | 120 | return false; |
121 | } | 121 | } |
122 | 122 | ||
123 | // Note that the agent string is provided simply to differentiate | ||
124 | // the handlers - it is NOT required to be an actual agent header | ||
125 | // value. | ||
126 | |||
123 | public bool AddAgentHandler(string agent, IHttpAgentHandler handler) | 127 | public bool AddAgentHandler(string agent, IHttpAgentHandler handler) |
124 | { | 128 | { |
125 | if (!m_agentHandlers.ContainsKey(agent)) | 129 | if (!m_agentHandlers.ContainsKey(agent)) |
@@ -149,7 +153,7 @@ namespace OpenSim.Framework.Servers | |||
149 | { | 153 | { |
150 | HttpListenerContext context = (HttpListenerContext) stateinfo; | 154 | HttpListenerContext context = (HttpListenerContext) stateinfo; |
151 | 155 | ||
152 | OSHttpRequest request = new OSHttpRequest(context.Request); | 156 | OSHttpRequest request = new OSHttpRequest(context.Request); |
153 | OSHttpResponse response = new OSHttpResponse(context.Response); | 157 | OSHttpResponse response = new OSHttpResponse(context.Response); |
154 | 158 | ||
155 | if (request.UserAgent != null) | 159 | if (request.UserAgent != null) |
@@ -157,11 +161,11 @@ namespace OpenSim.Framework.Servers | |||
157 | 161 | ||
158 | IHttpAgentHandler agentHandler; | 162 | IHttpAgentHandler agentHandler; |
159 | 163 | ||
160 | if (TryGetAgentHandler(request.UserAgent, out agentHandler)) | 164 | if (TryGetAgentHandler(request, response, out agentHandler)) |
161 | { | 165 | { |
162 | m_log.DebugFormat("[HTTP-AGENT] Handler located for {0}", request.UserAgent); | 166 | // m_log.DebugFormat("[HTTP-AGENT] Handler located for {0}", request.UserAgent); |
163 | HandleAgentRequest(agentHandler, request, response); | 167 | if(HandleAgentRequest(agentHandler, request, response)) |
164 | return; | 168 | return; |
165 | } | 169 | } |
166 | } | 170 | } |
167 | 171 | ||
@@ -301,14 +305,14 @@ namespace OpenSim.Framework.Servers | |||
301 | } | 305 | } |
302 | } | 306 | } |
303 | 307 | ||
304 | private bool TryGetAgentHandler(string agent, out IHttpAgentHandler agentHandler) | 308 | private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) |
305 | { | 309 | { |
306 | agentHandler = null; | 310 | agentHandler = null; |
307 | try | 311 | try |
308 | { | 312 | { |
309 | foreach(IHttpAgentHandler handler in m_agentHandlers.Values) | 313 | foreach(IHttpAgentHandler handler in m_agentHandlers.Values) |
310 | { | 314 | { |
311 | if(handler.Match(agent)) | 315 | if(handler.Match(request, response)) |
312 | { | 316 | { |
313 | agentHandler = handler; | 317 | agentHandler = handler; |
314 | return true; | 318 | return true; |
@@ -472,7 +476,7 @@ namespace OpenSim.Framework.Servers | |||
472 | /// <param name="request"></param> | 476 | /// <param name="request"></param> |
473 | /// <param name="response"></param> | 477 | /// <param name="response"></param> |
474 | 478 | ||
475 | private void HandleAgentRequest(IHttpAgentHandler handler, OSHttpRequest request, OSHttpResponse response) | 479 | private bool HandleAgentRequest(IHttpAgentHandler handler, OSHttpRequest request, OSHttpResponse response) |
476 | { | 480 | { |
477 | 481 | ||
478 | // In the case of REST, then handler is responsible for ALL aspects of | 482 | // In the case of REST, then handler is responsible for ALL aspects of |
@@ -480,17 +484,27 @@ namespace OpenSim.Framework.Servers | |||
480 | 484 | ||
481 | try | 485 | try |
482 | { | 486 | { |
483 | handler.Handle(request, response); | 487 | return handler.Handle(request, response); |
484 | } | 488 | } |
485 | catch (Exception e) | 489 | catch (Exception e) |
486 | { | 490 | { |
487 | m_log.Warn("[HTTP-AGENT]: Error - " + e.Message); | 491 | // If the handler did in fact close the stream, then this will blow |
488 | response.SendChunked = false; | 492 | // chunks, so that that doesn;t disturb anybody we throw away any |
489 | response.KeepAlive = false; | 493 | // and all exceptions raised. We've done our best to release the |
490 | response.StatusCode = 500; | 494 | // client. |
491 | response.OutputStream.Close(); | 495 | try |
496 | { | ||
497 | m_log.Warn("[HTTP-AGENT]: Error - " + e.Message); | ||
498 | response.SendChunked = false; | ||
499 | response.KeepAlive = false; | ||
500 | response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError; | ||
501 | response.OutputStream.Close(); | ||
502 | } | ||
503 | catch(Exception){} | ||
492 | } | 504 | } |
493 | 505 | ||
506 | return true; | ||
507 | |||
494 | } | 508 | } |
495 | 509 | ||
496 | public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) | 510 | public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) |
@@ -498,7 +512,7 @@ namespace OpenSim.Framework.Servers | |||
498 | switch (request.HttpMethod) | 512 | switch (request.HttpMethod) |
499 | { | 513 | { |
500 | case "OPTIONS": | 514 | case "OPTIONS": |
501 | response.StatusCode = 200; | 515 | response.StatusCode = (int)OSHttpStatusCode.SuccessOk; |
502 | return; | 516 | return; |
503 | 517 | ||
504 | default: | 518 | default: |
@@ -599,9 +613,9 @@ namespace OpenSim.Framework.Servers | |||
599 | // We're forgoing the usual error status codes here because the client | 613 | // We're forgoing the usual error status codes here because the client |
600 | // ignores anything but 200 and 301 | 614 | // ignores anything but 200 and 301 |
601 | 615 | ||
602 | response.StatusCode = 200; | 616 | response.StatusCode = (int)OSHttpStatusCode.SuccessOk; |
603 | 617 | ||
604 | if (responsecode == 301) | 618 | if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) |
605 | { | 619 | { |
606 | response.RedirectLocation = (string)responsedata["str_redirect_location"]; | 620 | response.RedirectLocation = (string)responsedata["str_redirect_location"]; |
607 | response.StatusCode = responsecode; | 621 | response.StatusCode = responsecode; |
@@ -632,7 +646,7 @@ namespace OpenSim.Framework.Servers | |||
632 | public void SendHTML404(OSHttpResponse response, string host) | 646 | public void SendHTML404(OSHttpResponse response, string host) |
633 | { | 647 | { |
634 | // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s | 648 | // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s |
635 | response.StatusCode = 200; | 649 | response.StatusCode = (int)OSHttpStatusCode.SuccessOk; |
636 | response.AddHeader("Content-type", "text/html"); | 650 | response.AddHeader("Content-type", "text/html"); |
637 | 651 | ||
638 | string responseString = GetHTTP404(host); | 652 | string responseString = GetHTTP404(host); |
@@ -659,7 +673,7 @@ namespace OpenSim.Framework.Servers | |||
659 | public void SendHTML500(OSHttpResponse response) | 673 | public void SendHTML500(OSHttpResponse response) |
660 | { | 674 | { |
661 | // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s | 675 | // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s |
662 | response.StatusCode = 200; | 676 | response.StatusCode = (int)OSHttpStatusCode.SuccessOk; |
663 | response.AddHeader("Content-type", "text/html"); | 677 | response.AddHeader("Content-type", "text/html"); |
664 | 678 | ||
665 | string responseString = GetHTTP500(); | 679 | string responseString = GetHTTP500(); |
@@ -738,6 +752,23 @@ namespace OpenSim.Framework.Servers | |||
738 | m_HTTPHandlers.Remove(GetHandlerKey(httpMethod, path)); | 752 | m_HTTPHandlers.Remove(GetHandlerKey(httpMethod, path)); |
739 | } | 753 | } |
740 | 754 | ||
755 | // Remove the agent IF it is registered. Intercept the possible | ||
756 | // exception. | ||
757 | |||
758 | public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) | ||
759 | { | ||
760 | try | ||
761 | { | ||
762 | if(handler == m_agentHandlers[agent]) | ||
763 | { | ||
764 | m_agentHandlers.Remove(agent); | ||
765 | return true; | ||
766 | } | ||
767 | } | ||
768 | catch(KeyNotFoundException) {} | ||
769 | return false; | ||
770 | } | ||
771 | |||
741 | public string GetHTTP404(string host) | 772 | public string GetHTTP404(string host) |
742 | { | 773 | { |
743 | string file = Path.Combine(Util.configDir(), "http_404.html"); | 774 | string file = Path.Combine(Util.configDir(), "http_404.html"); |
diff --git a/OpenSim/Framework/Servers/IHttpAgentHandler.cs b/OpenSim/Framework/Servers/IHttpAgentHandler.cs index 9bca150..ff3a5b9 100644 --- a/OpenSim/Framework/Servers/IHttpAgentHandler.cs +++ b/OpenSim/Framework/Servers/IHttpAgentHandler.cs | |||
@@ -33,7 +33,7 @@ namespace OpenSim.Framework.Servers | |||
33 | { | 33 | { |
34 | public interface IHttpAgentHandler | 34 | public interface IHttpAgentHandler |
35 | { | 35 | { |
36 | void Handle(OSHttpRequest req, OSHttpResponse resp); | 36 | bool Handle(OSHttpRequest req, OSHttpResponse resp); |
37 | bool Match(string agent); | 37 | bool Match(OSHttpRequest req, OSHttpResponse resp); |
38 | } | 38 | } |
39 | } | 39 | } |
diff --git a/OpenSim/Framework/Servers/OSHttpStatusCodes.cs b/OpenSim/Framework/Servers/OSHttpStatusCodes.cs new file mode 100644 index 0000000..2e001cf --- /dev/null +++ b/OpenSim/Framework/Servers/OSHttpStatusCodes.cs | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | namespace OpenSim.Framework.Servers | ||
29 | { | ||
30 | /// <summary> | ||
31 | /// HTTP status codes (almost) as defined by W3C in | ||
32 | /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html | ||
33 | /// </summary> | ||
34 | public enum OSHttpStatusCode: int | ||
35 | { | ||
36 | // 1xx Informational status codes providing a provisional | ||
37 | // response. | ||
38 | // 100 Tells client that to keep on going sending its request | ||
39 | InfoContinue = 100, | ||
40 | // 101 Server understands request, proposes to switch to different | ||
41 | // application level protocol | ||
42 | InfoSwitchingProtocols = 101, | ||
43 | |||
44 | |||
45 | // 2xx Success codes | ||
46 | // 200 Request successful | ||
47 | SuccessOk = 200, | ||
48 | // 201 Request successful, new resource created | ||
49 | SuccessOkCreated = 201, | ||
50 | // 202 Request accepted, processing still on-going | ||
51 | SuccessOkAccepted = 202, | ||
52 | // 203 Request successful, meta information not authoritative | ||
53 | SuccessOkNonAuthoritativeInformation = 203, | ||
54 | // 204 Request successful, nothing to return in the body | ||
55 | SuccessOkNoContent = 204, | ||
56 | // 205 Request successful, reset displayed content | ||
57 | SuccessOkResetContent = 205, | ||
58 | // 206 Request successful, partial content returned | ||
59 | SuccessOkPartialContent = 206, | ||
60 | |||
61 | // 3xx Redirect code: user agent needs to go somewhere else | ||
62 | // 300 Redirect: different presentation forms available, take | ||
63 | // a pick | ||
64 | RedirectMultipleChoices = 300, | ||
65 | // 301 Redirect: requested resource has moved and now lives | ||
66 | // somewhere else | ||
67 | RedirectMovedPermanently = 301, | ||
68 | // 302 Redirect: Resource temporarily somewhere else, location | ||
69 | // might change | ||
70 | RedirectFound = 302, | ||
71 | // 303 Redirect: See other as result of a POST | ||
72 | RedirectSeeOther = 303, | ||
73 | // 304 Redirect: Resource still the same as before | ||
74 | RedirectNotModified = 304, | ||
75 | // 305 Redirect: Resource must be accessed via proxy provided | ||
76 | // in location field | ||
77 | RedirectUseProxy = 305, | ||
78 | // 307 Redirect: Resource temporarily somewhere else, location | ||
79 | // might change | ||
80 | RedirectMovedTemporarily = 307, | ||
81 | |||
82 | // 4xx Client error: the client borked the request | ||
83 | // 400 Client error: bad request, server does not grok what | ||
84 | // the client wants | ||
85 | ClientErrorBadRequest = 400, | ||
86 | // 401 Client error: the client is not authorized, response | ||
87 | // provides WWW-Authenticate header field with a challenge | ||
88 | ClientErrorUnauthorized = 401, | ||
89 | // 402 Client error: Payment required (reserved for future use) | ||
90 | ClientErrorPaymentRequired = 402, | ||
91 | // 403 Client error: Server understood request, will not | ||
92 | // deliver, do not try again. | ||
93 | ClientErrorForbidden = 403, | ||
94 | // 404 Client error: Server cannot find anything matching the | ||
95 | // client request. | ||
96 | ClientErrorNotFound = 404, | ||
97 | // 405 Client error: The method specified by the client in the | ||
98 | // request is not allowed for the resource requested | ||
99 | ClientErrorMethodNotAllowed = 405, | ||
100 | // 406 Client error: Server cannot generate suitable response | ||
101 | // for the resource and content characteristics requested by | ||
102 | // the client | ||
103 | ClientErrorNotAcceptable = 406, | ||
104 | // 407 Client error: Similar to 401, Server requests that | ||
105 | // client authenticate itself with the proxy first | ||
106 | ClientErrorProxyAuthRequired = 407, | ||
107 | // 408 Client error: Server got impatient with client and | ||
108 | // decided to give up waiting for the client's request to | ||
109 | // arrive | ||
110 | ClientErrorRequestTimeout = 408, | ||
111 | // 409 Client error: Server could not fulfill the request for | ||
112 | // a resource as there is a conflict with the current state of | ||
113 | // the resource but thinks client can do something about this | ||
114 | ClientErrorConflict = 409, | ||
115 | // 410 Client error: The resource has moved somewhere else, | ||
116 | // but server has no clue where. | ||
117 | ClientErrorGone = 410, | ||
118 | // 411 Client error: The server is picky again and insists on | ||
119 | // having a content-length header field in the request | ||
120 | ClientErrorLengthRequired = 411, | ||
121 | // 412 Client error: one or more preconditions supplied in the | ||
122 | // client's request is false | ||
123 | ClientErrorPreconditionFailed = 412, | ||
124 | // 413 Client error: For fear of reflux, the server refuses to | ||
125 | // swallow that much data. | ||
126 | ClientErrorRequestEntityToLarge = 413, | ||
127 | // 414 Client error: The server considers the Request-URI to | ||
128 | // be indecently long and refuses to even look at it. | ||
129 | ClientErrorRequestURITooLong = 414, | ||
130 | // 415 Client error: The server has no clue about the media | ||
131 | // type requested by the client (contrary to popular belief it | ||
132 | // is not a warez server) | ||
133 | ClientErrorUnsupportedMediaType = 415, | ||
134 | // 416 Client error: The requested range cannot be delivered | ||
135 | // by the server. | ||
136 | ClientErrorRequestRangeNotSatisfiable = 416, | ||
137 | // 417 Client error: The expectations of the client as | ||
138 | // expressed in one or more Expect header fields cannot be met | ||
139 | // by the server, the server is awfully sorry about this. | ||
140 | ClientErrorExpectationFailed = 417, | ||
141 | |||
142 | // 5xx Server errors (rare) | ||
143 | // 500 Server error: something really strange and unexpected | ||
144 | // happened | ||
145 | ServerErrorInternalError = 500, | ||
146 | // 501 Server error: The server does not do the functionality | ||
147 | // required to carry out the client request. not at | ||
148 | // all. certainly not before breakfast. but also not after | ||
149 | // breakfast. | ||
150 | ServerErrorNotImplemented = 501, | ||
151 | // 502 Server error: While acting as a proxy or a gateway, the | ||
152 | // server got ditched by the upstream server and as a | ||
153 | // consequence regretfully cannot fulfill the client's request | ||
154 | ServerErrorBadGateway = 502, | ||
155 | // 503 Server error: Due to unforseen circumstances the server | ||
156 | // cannot currently deliver the service requested. Retry-After | ||
157 | // header might indicate when to try again. | ||
158 | ServerErrorServiceUnavailable = 503, | ||
159 | // 504 Server error: The server blames the upstream server | ||
160 | // for not being able to deliver the service requested and | ||
161 | // claims that the upstream server is too slow delivering the | ||
162 | // goods. | ||
163 | ServerErrorGatewayTimeout = 504, | ||
164 | // 505 Server error: The server does not support the HTTP | ||
165 | // version conveyed in the client's request. | ||
166 | ServerErrorHttpVersionNotSupported = 505, | ||
167 | } | ||
168 | } | ||