示例#1
0
        private static async Task RequestReceived(HttpContext ctx)
        {
            string   header    = "[Komodo.Server] " + ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " RequestReceived ";
            DateTime startTime = DateTime.Now;

            try
            {
                #region Base-Handlers

                if (ctx.Request.Method == HttpMethod.OPTIONS)
                {
                    await OptionsHandler(ctx);

                    return;
                }

                if (ctx.Request.Url.Elements == null || ctx.Request.Url.Elements.Length == 0)
                {
                    ctx.Response.StatusCode  = 200;
                    ctx.Response.ContentType = "text/html; charset=utf-8";
                    await ctx.Response.Send(RootHtml());

                    return;
                }

                if (ctx.Request.Url.Elements != null && ctx.Request.Url.Elements.Length > 0)
                {
                    if (ctx.Request.Url.Elements.Length == 1)
                    {
                        if (String.Compare(ctx.Request.Url.Elements[0].ToLower(), "favicon.ico") == 0)
                        {
                            ctx.Response.StatusCode = 200;
                            await ctx.Response.Send(Common.ReadBinaryFile("Assets/favicon.ico"));

                            return;
                        }

                        if (String.Compare(ctx.Request.Url.Elements[0].ToLower(), "robots.txt") == 0)
                        {
                            ctx.Response.StatusCode  = 200;
                            ctx.Response.ContentType = "text/plain";
                            await ctx.Response.Send("User-Agent: *\r\nDisallow:\r\n");

                            return;
                        }

                        if (String.Compare(ctx.Request.Url.Elements[0].ToLower(), "loopback") == 0)
                        {
                            ctx.Response.StatusCode = 200;
                            await ctx.Response.Send();

                            return;
                        }

                        if (String.Compare(ctx.Request.Url.Elements[0].ToLower(), "version") == 0)
                        {
                            ctx.Response.StatusCode  = 200;
                            ctx.Response.ContentType = "text/plain";
                            await ctx.Response.Send(_Version);

                            return;
                        }
                    }
                }

                #endregion

                #region Admin-API

                string apiKey = ctx.Request.RetrieveHeaderValue(_Settings.Server.HeaderApiKey);

                if (ctx.Request.Url.Elements != null &&
                    ctx.Request.Url.Elements.Length > 0 &&
                    ctx.Request.Url.Elements[0].Equals("admin"))
                {
                    if (String.IsNullOrEmpty(apiKey))
                    {
                        _Logging.Warn(header + "admin API requested but no API key specified");
                        ctx.Response.StatusCode  = 401;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(new ErrorResponse(401, "No API key specified.", null, null).ToJson(true));

                        return;
                    }

                    if (String.Compare(_Settings.Server.AdminApiKey, apiKey) != 0)
                    {
                        _Logging.Warn(header + "admin API requested with invalid API key");
                        ctx.Response.StatusCode  = 401;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(new ErrorResponse(401, "Authentication failed.", null, null).ToJson(true));

                        return;
                    }

                    await AdminApiHandler(ctx);

                    return;
                }

                #endregion

                #region Determine-Request-Type

                PermissionType permType = PermissionType.Unknown;

                if (ctx.Request.Url.Elements.Length == 1)
                {
                    if (ctx.Request.Method == HttpMethod.GET && ctx.Request.Url.Elements[0].Equals("indices"))
                    {
                        // GET /indices, i.e. search
                        permType = PermissionType.Search;
                    }
                    else if (ctx.Request.Method == HttpMethod.GET)
                    {
                        // GET /[index], i.e. search
                        permType = PermissionType.Search;
                    }
                    else if (ctx.Request.Method == HttpMethod.PUT)
                    {
                        // PUT /[index], i.e. search
                        // PUT /[index]?enumerate, i.e. search
                        permType = PermissionType.Search;
                    }
                    else if (ctx.Request.Method == HttpMethod.POST)
                    {
                        if (ctx.Request.Url.Elements[0].Equals("_parse"))
                        {
                            // POST /_parse, i.e. parse document (without storing)
                            permType = PermissionType.CreateDocument;
                        }
                        else if (ctx.Request.Url.Elements[0].Equals("_postings"))
                        {
                            // POST /_postings, i.e. create postings (without storing)
                            permType = PermissionType.CreateDocument;
                        }
                        else if (ctx.Request.Url.Elements[0].Equals("indices"))
                        {
                            // POST /indices, i.e. create index
                            permType = PermissionType.CreateIndex;
                        }
                        else
                        {
                            // POST /[index], i.e. create document
                            permType = PermissionType.CreateDocument;
                        }
                    }
                    else if (ctx.Request.Method == HttpMethod.DELETE)
                    {
                        // DELETE /[index], i.e. delete index
                        permType = PermissionType.DeleteIndex;
                    }
                }
                else if (ctx.Request.Url.Elements.Length == 2)
                {
                    if (ctx.Request.Method == HttpMethod.GET)
                    {
                        if (ctx.Request.Url.Elements[1].Equals("stats"))
                        {
                            // GET /[index]/stats, i.e. search
                            permType = PermissionType.Search;
                        }
                        else
                        {
                            // GET /[index]/[documentID], i.e. search
                            permType = PermissionType.Search;
                        }
                    }
                    else if (ctx.Request.Method == HttpMethod.POST)
                    {
                        // POST /[index]/[document], i.e. create document with specific GUID
                        permType = PermissionType.CreateDocument;
                    }
                    else if (ctx.Request.Method == HttpMethod.DELETE)
                    {
                        // DELETE /[index]/[document], i.e. delete document
                        permType = PermissionType.DeleteDocument;
                    }
                }

                if (permType == PermissionType.Unknown)
                {
                    _Logging.Warn(header + "unable to verify request type");
                    ctx.Response.StatusCode  = 400;
                    ctx.Response.ContentType = "application/json";
                    await ctx.Response.Send(new ErrorResponse(400, "Unable to discern request type.", null, null).ToJson(true));

                    return;
                }

                #endregion

                #region Authenticate-Request-and-Build-Metadata

                User       user = null;
                ApiKey     key  = null;
                Permission perm = null;

                if (!String.IsNullOrEmpty(apiKey))
                {
                    if (!_Auth.AuthenticateAndAuthorize(apiKey, permType, out user, out key, out perm))
                    {
                        _Logging.Warn(header + "unable to authenticate and authorize request");
                        ctx.Response.StatusCode  = 401;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(new ErrorResponse(401, "Unable to authenticate or authorize request.", null, null).ToJson(true));

                        return;
                    }
                }
                else
                {
                    _Logging.Warn(header + "authenticated API requested but no authentication material supplied");
                    ctx.Response.StatusCode  = 401;
                    ctx.Response.ContentType = "application/json";
                    await ctx.Response.Send(new ErrorResponse(401, "No authentication material.", null, null).ToJson(true));

                    return;
                }

                RequestMetadata md = new RequestMetadata(ctx, user, key, perm);

                if (!String.IsNullOrEmpty(md.Params.Type))
                {
                    List <string> matchVals = new List <string> {
                        "json", "xml", "html", "sql", "text", "unknown"
                    };
                    if (!matchVals.Contains(md.Params.Type))
                    {
                        _Logging.Warn(header + "invalid 'type' value found in querystring: " + md.Params.Type);
                        ctx.Response.StatusCode  = 400;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(new ErrorResponse(400, "Invalid 'type' in querystring, use [json/xml/html/sql/text].", null, null).ToJson(true));

                        return;
                    }
                }

                #endregion

                #region Call-User-API

                await UserApiHandler(md);

                return;

                #endregion
            }
            catch (Exception e)
            {
                _Logging.Alert(header + "exception encountered" + Environment.NewLine + Common.SerializeJson(e, true));
                ctx.Response.StatusCode  = 500;
                ctx.Response.ContentType = "application/json";
                await ctx.Response.Send(new ErrorResponse(500, "Outer exception.", e, null).ToJson(true));

                return;
            }
            finally
            {
                _Logging.Debug(header + ctx.Request.Method + " " + ctx.Request.Url.RawWithoutQuery + " " + ctx.Response.StatusCode + " [" + Common.TotalMsFrom(startTime) + "ms]");
            }
        }