static HttpResponse RequestHandler(HttpRequest req) { DateTime startTime = DateTime.Now; HttpResponse resp = null; bool connAdded = false; try { #region Unauthenticated-APIs switch (req.Method) { case HttpMethod.GET: if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/loopback", false)) { resp = new HttpResponse(req, true, 200, null, "application/json", "Hello from CryptoServer!", false); return(resp); } break; case HttpMethod.PUT: case HttpMethod.POST: case HttpMethod.DELETE: default: break; } #endregion #region Add-to-Connection-List _Connections.Add(Thread.CurrentThread.ManagedThreadId, req); connAdded = true; #endregion #region APIs if (!String.IsNullOrEmpty(req.RetrieveHeaderValue(_Settings.Auth.ApiKeyHeader))) { if (req.RetrieveHeaderValue(_Settings.Auth.ApiKeyHeader).Equals(_Settings.Auth.AdminApiKey)) { #region Admin-API-Key _Logging.Log(LoggingModule.Severity.Info, "RequestHandler use of admin API key detected for: " + req.RawUrlWithoutQuery); switch (req.Method) { case HttpMethod.GET: if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_cryptoserver/connections", false)) { resp = new HttpResponse(req, true, 200, null, "application/json", _Connections.GetActiveConnections(), false); return(resp); } if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_cryptoserver/config", false)) { resp = new HttpResponse(req, true, 200, null, "application/json", _Settings, false); return(resp); } break; case HttpMethod.PUT: case HttpMethod.POST: case HttpMethod.DELETE: default: break; } _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unknown admin API endpoint: " + req.RawUrlWithoutQuery); resp = new HttpResponse(req, false, 400, null, "application/json", "Unknown API endpoint or verb", false); return(resp); #endregion } else if (req.RetrieveHeaderValue(_Settings.Auth.ApiKeyHeader).Equals(_Settings.Auth.CryptoApiKey)) { #region Crypto-API-Key string failureReason; byte[] responseData; Obj responseObj; switch (req.Method) { case HttpMethod.POST: if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/decrypt", false)) { Obj reqObj = Common.DeserializeJson <Obj>(req.Data); if (!_Crypto.Decrypt(reqObj, out responseData, out failureReason)) { _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unable to decrypt: " + failureReason); resp = new HttpResponse(req, false, 500, null, "application/json", failureReason, false); return(resp); } else { _Logging.Log(LoggingModule.Severity.Debug, "RequestHandler encrypt returning " + responseData.Length + " bytes"); resp = new HttpResponse(req, true, 200, null, "application/octet-stream", responseData, true); return(resp); } } if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/encrypt", false)) { if (!_Crypto.Encrypt(req.Data, out responseObj, out failureReason)) { _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unable to encrypt: " + failureReason); resp = new HttpResponse(req, false, 500, null, "application/json", failureReason, false); return(resp); } else { resp = new HttpResponse(req, true, 200, null, "application/json", Common.SerializeJson(responseObj), true); return(resp); } } break; case HttpMethod.GET: case HttpMethod.PUT: case HttpMethod.DELETE: default: break; } _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unknown crypto API endpoint: " + req.RawUrlWithoutQuery); resp = new HttpResponse(req, false, 400, null, "application/json", "Unknown API endpoint or verb", false); return(resp); #endregion } else { #region Invalid-Auth-Material _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler invalid API key supplied: " + req.RetrieveHeaderValue(_Settings.Auth.ApiKeyHeader)); resp = new HttpResponse(req, false, 401, null, "application/json", "Invalid API key", false); return(resp); #endregion } } resp = new HttpResponse(req, false, 401, null, "application/json", "No authentication material", false); return(resp); #endregion } catch (Exception e) { _Logging.LogException("CryptoServer", "RequestHandler", e); resp = new HttpResponse(req, false, 500, null, "application/json", "Internal server error", false); return(resp); } finally { if (resp != null) { string message = "RequestHandler " + req.SourceIp + ":" + req.SourcePort + " " + req.Method + " " + req.RawUrlWithoutQuery; message += " " + resp.StatusCode + " " + Common.TotalMsFrom(startTime) + "ms"; _Logging.Log(LoggingModule.Severity.Debug, message); } if (connAdded) { _Connections.Close(Thread.CurrentThread.ManagedThreadId); } } }
static HttpResponse RequestHandler(HttpRequest req) { DateTime startTime = DateTime.Now; HttpResponse resp = null; Host currHost = null; Node currNode = null; string hostKey = null; bool connAdded = false; try { #region Unauthenticated-APIs switch (req.Method) { case HttpMethod.GET: if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_loadbalancer/loopback", false)) { resp = new HttpResponse(req, true, 200, null, "application/json", "Hello from LoadBalancer!", false); return(resp); } break; case HttpMethod.PUT: case HttpMethod.POST: case HttpMethod.DELETE: default: break; } #endregion #region Add-to-Connection-List _Connections.Add(Thread.CurrentThread.ManagedThreadId, req); connAdded = true; #endregion #region Authenticate-and-Admin-APIs if (!String.IsNullOrEmpty(req.RetrieveHeaderValue(_Settings.Auth.AdminApiKeyHeader))) { if (req.RetrieveHeaderValue(_Settings.Auth.AdminApiKeyHeader).Equals(_Settings.Auth.AdminApiKey)) { #region Admin-APIs _Logging.Log(LoggingModule.Severity.Info, "RequestHandler use of admin API key detected for: " + req.RawUrlWithoutQuery); switch (req.Method) { case HttpMethod.GET: if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_loadbalancer/connections", false)) { resp = new HttpResponse(req, true, 200, null, "application/json", _Connections.GetActiveConnections(), false); return(resp); } if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_loadbalancer/config", false)) { resp = new HttpResponse(req, true, 200, null, "application/json", _Settings, false); return(resp); } if (WatsonCommon.UrlEqual(req.RawUrlWithoutQuery, "/_loadbalancer/hosts", false)) { resp = new HttpResponse(req, true, 200, null, "application/json", _Hosts.Get(), false); return(resp); } break; case HttpMethod.PUT: case HttpMethod.POST: case HttpMethod.DELETE: default: break; } _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler unknown admin API endpoint: " + req.RawUrlWithoutQuery); resp = new HttpResponse(req, false, 400, null, "application/json", "Unknown API endpoint or verb", false); return(resp); #endregion } else { #region Failed-Auth _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler invalid admin API key supplied: " + req.RetrieveHeaderValue(_Settings.Auth.AdminApiKeyHeader)); resp = new HttpResponse(req, false, 401, null, "application/json", "Authentication failed", false); return(resp); #endregion } } #endregion #region Find-Host-and-Node if (req.Headers.ContainsKey("Host")) { hostKey = req.RetrieveHeaderValue("Host"); } if (String.IsNullOrEmpty(hostKey)) { _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler no host header supplied for " + req.SourceIp + ":" + req.SourceIp + " " + req.Method + " " + req.RawUrlWithoutQuery); resp = new HttpResponse(req, false, 400, null, "application/json", "No host header supplied", false); return(resp); } if (!_Hosts.SelectNodeForHost(hostKey, out currHost, out currNode)) { _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler host or node not found for " + req.SourceIp + ":" + req.SourceIp + " " + req.Method + " " + req.RawUrlWithoutQuery); resp = new HttpResponse(req, false, 400, null, "application/json", "Host or node not found", false); return(resp); } else { if (currHost == null || currHost == default(Host)) { _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler host not found for " + req.SourceIp + ":" + req.SourceIp + " " + req.Method + " " + req.RawUrlWithoutQuery); resp = new HttpResponse(req, false, 400, null, "application/json", "Host not found", false); return(resp); } if (currNode == null || currNode == default(Node)) { _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler node not found for " + req.SourceIp + ":" + req.SourceIp + " " + req.Method + " " + req.RawUrlWithoutQuery); resp = new HttpResponse(req, false, 400, null, "application/json", "No node found for host", false); return(resp); } _Connections.Update(Thread.CurrentThread.ManagedThreadId, hostKey, currHost.Name, currNode.Hostname); } #endregion #region Process-Connection if (currHost.HandlingMode == HandlingMode.Redirect) { #region Redirect string redirectUrl = BuildProxyUrl(currNode, req); // add host header Dictionary <string, string> requestHeaders = new Dictionary <string, string>(); // add other headers if (req.Headers != null && req.Headers.Count > 0) { List <string> matchHeaders = new List <string> { "host", "connection", "user-agent" }; foreach (KeyValuePair <string, string> currHeader in req.Headers) { if (matchHeaders.Contains(currHeader.Key.ToLower().Trim())) { continue; } else { requestHeaders.Add(currHeader.Key, currHeader.Value); } } } // process REST request RestResponse restResp = RestRequest.SendRequestSafe( redirectUrl, req.ContentType, req.Method.ToString(), null, null, false, Common.IsTrue(currHost.AcceptInvalidCerts), requestHeaders, req.Data); if (restResp == null) { _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler null proxy response from " + redirectUrl); resp = new HttpResponse(req, false, 500, null, "application/json", "Unable to contact node", false); return(resp); } else { resp = new HttpResponse(req, true, restResp.StatusCode, restResp.Headers, restResp.ContentType, restResp.Data, true); return(resp); } #endregion } else if (currHost.HandlingMode == HandlingMode.Proxy) { #region Proxy string redirectUrl = BuildProxyUrl(currNode, req); Dictionary <string, string> redirectHeaders = new Dictionary <string, string>(); redirectHeaders.Add("location", redirectUrl); resp = new HttpResponse(req, true, _Settings.RedirectStatusCode, redirectHeaders, "text/plain", _Settings.RedirectStatusString, true); return(resp); #endregion } else { #region Unknown-Handling-Mode _Logging.Log(LoggingModule.Severity.Warn, "RequestHandler invalid handling mode " + currHost.HandlingMode + " for host " + currHost.Name); resp = new HttpResponse(req, false, 500, null, "application/json", "Invalid handling mode '" + currHost.HandlingMode + "'", false); return(resp); #endregion } #endregion } catch (Exception e) { _Logging.LogException("LoadBalancer", "RequestHandler", e); resp = new HttpResponse(req, false, 500, null, "application/json", "Internal server error", false); return(resp); } finally { if (resp != null) { string message = "RequestHandler " + req.SourceIp + ":" + req.SourcePort + " " + req.Method + " " + req.RawUrlWithoutQuery; if (currNode != null) { message += " " + hostKey + " to " + currNode.Hostname + ":" + currNode.Port + " " + currHost.HandlingMode; } message += " " + resp.StatusCode + " " + Common.TotalMsFrom(startTime) + "ms"; _Logging.Log(LoggingModule.Severity.Debug, message); } if (connAdded) { _Connections.Close(Thread.CurrentThread.ManagedThreadId); } } }