コード例 #1
0
ファイル: Server.cs プロジェクト: jchristn/RestDb
        static async Task DefaultRoute(HttpContext ctx)
        {
            DateTime startTime = DateTime.Now;
            string   header    = ctx.Request.Source.IpAddress + ":" + ctx.Request.Source.Port + " ";

            _Logging.Debug(header + ctx.Request.Method + " " + ctx.Request.Url.RawWithoutQuery);

            #region APIs

            try
            {
                #region Unauthenticated-Methods

                switch (ctx.Request.Method)
                {
                case HttpMethod.GET:
                    #region get

                    if (ctx.Request.Url.RawWithoutQuery.Equals("/"))
                    {
                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/html; charset=utf8";
                        await ctx.Response.Send(RootHtml());

                        return;
                    }

                    if (ctx.Request.Url.RawWithoutQuery.Equals("/favicon.ico") ||
                        ctx.Request.Url.RawWithoutQuery.Equals("/robots.txt"))
                    {
                        ctx.Response.StatusCode = 200;
                        await ctx.Response.Send();

                        return;
                    }
                    break;

                    #endregion

                case HttpMethod.PUT:
                    #region put

                    break;

                    #endregion

                case HttpMethod.POST:
                    #region post

                    break;

                    #endregion

                case HttpMethod.DELETE:
                    #region delete

                    break;

                    #endregion

                default:
                    ctx.Response.StatusCode  = 400;
                    ctx.Response.ContentType = "application/json";
                    await ctx.Response.Send(SerializationHelper.SerializeJson(new ErrorResponse(ErrorCodeEnum.InvalidRequest, "Unknown method", null), true));

                    return;
                }

                #endregion

                #region Build-Metadata

                RequestMetadata md = new RequestMetadata(ctx);

                #endregion

                #region Authenticate

                if (_Settings.Server.RequireAuthentication)
                {
                    string apiKey = null;
                    ApiKey key    = null;

                    if (!_Auth.Authenticate(ctx, out apiKey, out key))
                    {
                        _Logging.Warn(header + "authentication failed");
                        ctx.Response.StatusCode  = 401;
                        ctx.Response.ContentType = "application/json";
                        await ctx.Response.Send(SerializationHelper.SerializeJson(new ErrorResponse(ErrorCodeEnum.NotAuthenticated, "You are not authorized to perform this operation", null), true));

                        return;
                    }

                    md.ApiKey        = key;
                    md.Params.ApiKey = apiKey;
                }

                if (md.Params.Metadata)
                {
                    ctx.Response.StatusCode  = 200;
                    ctx.Response.ContentType = "application/json";
                    await ctx.Response.Send(SerializationHelper.SerializeJson(md, true));

                    return;
                }

                #endregion

                #region Authenticated-Methods

                switch (ctx.Request.Method)
                {
                case HttpMethod.GET:
                    #region get

                    if (ctx.Request.Url.RawWithoutQuery.Equals("/_databaseclients"))
                    {
                        await GetDatabaseClients(md);

                        return;
                    }

                    if (ctx.Request.Url.RawWithoutQuery.Equals("/_databases"))
                    {
                        await GetDatabases(md);

                        return;
                    }

                    if (ctx.Request.Url.Elements.Length == 1)
                    {
                        await GetDatabase(md);

                        return;
                    }

                    if (ctx.Request.Url.Elements.Length == 2 || ctx.Request.Url.Elements.Length == 3)
                    {
                        await GetTableSelect(md);

                        return;
                    }

                    break;

                    #endregion

                case HttpMethod.PUT:
                    #region put

                    if (ctx.Request.Url.Elements.Length == 2 || ctx.Request.Url.Elements.Length == 3)
                    {
                        await PutTable(md);

                        return;
                    }
                    break;

                    #endregion

                case HttpMethod.POST:
                    #region post

                    if (ctx.Request.Url.Elements.Length == 1)
                    {
                        if (ctx.Request.Query.Elements.ContainsKey("raw"))
                        {
                            await PostRawQuery(md);

                            return;
                        }
                        else
                        {
                            await PostTableCreate(md);

                            return;
                        }
                    }

                    if (ctx.Request.Url.Elements.Length == 2)
                    {
                        await PostTableInsert(md);

                        return;
                    }
                    break;

                    #endregion

                case HttpMethod.DELETE:
                    #region delete

                    if (ctx.Request.Url.Elements.Length == 2 || ctx.Request.Url.Elements.Length == 3)
                    {
                        await DeleteTable(md);

                        return;
                    }
                    break;

                    #endregion

                default:
                    ctx.Response.StatusCode  = 400;
                    ctx.Response.ContentType = "application/json";
                    await ctx.Response.Send(SerializationHelper.SerializeJson(new ErrorResponse(ErrorCodeEnum.InvalidRequest, "Unknown method", null), true));

                    return;
                }

                #endregion

                ctx.Response.StatusCode  = 400;
                ctx.Response.ContentType = "application/json";
                await ctx.Response.Send(SerializationHelper.SerializeJson(new ErrorResponse(ErrorCodeEnum.InvalidRequest, "Unknown endpoint", null), true));
            }
            catch (Exception e)
            {
                _Logging.Exception(e);
                ctx.Response.StatusCode  = 500;
                ctx.Response.ContentType = "application/json";
                await ctx.Response.Send(SerializationHelper.SerializeJson(new ErrorResponse(ErrorCodeEnum.InternalError, "Internal server error", e.Message, e), true));
            }
            finally
            {
                _Logging.Debug(header + ctx.Request.Method + " " + ctx.Request.Url.RawWithoutQuery + " " + Common.TotalMsFrom(startTime) + "ms: " + ctx.Response.StatusCode);
            }

            #endregion
        }
コード例 #2
0
        private void RunSetup()
        {
            #region General

            if (Console.WindowWidth < 79)
            {
                Console.WindowWidth = 79;
            }

            Settings ret = new Settings();
            ret.Version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion;

            ret.Logging = LoggingSettings.Default();

            ret.ApiKeys = new List <ApiKey>();
            ret.ApiKeys.Add(ApiKey.Default());

            #endregion

            #region Server-Settings

            //                 0        1         2         3         4         5         6         7
            //                 1234567890123456789012345678901234567890123456789012345678901234567890123456789
            Console.WriteLine("RestDb Setup");
            Console.WriteLine("------------");
            Console.WriteLine("We'll collect some values and put together your initial configuration.");
            Console.WriteLine("");
            Console.WriteLine("On which hostname should this node listen?  The hostname supplied here MUST");
            Console.WriteLine("match the host header received on incoming RESTful HTTP requests.  It is");
            Console.WriteLine("recommended that you use the DNS hostname of the machine.");
            Console.WriteLine("");
            Console.WriteLine("Important: if you use localhost or 127.0.0.1, RestDb will only be able to");
            Console.WriteLine("accept requests from within the local system.  If you use *, +, or 0.0.0.0 to");
            Console.WriteLine("represent any address, you will have to run RestDb with admin privileges.");
            Console.WriteLine("");

            ret.Server = new ServerSettings();
            ret.Server.ListenerHostname = Common.InputString("Hostname?", "localhost", false);
            ret.Server.ListenerPort     = Common.InputInteger("Port number?", 8000, true, false);
            ret.Server.Ssl          = Common.InputBoolean("Require SSL?", false);
            ret.Server.Debug        = false;
            ret.Server.ApiKeyHeader = "x-api-key";

            Console.WriteLine("");

            #endregion

            #region Database-Settings

            List <Database> databases = new List <Database>();

            while (true)
            {
                Console.WriteLine("");
                Console.WriteLine("Databases");
                Console.WriteLine("---------");
                if (databases.Count > 0)
                {
                    Console.WriteLine("The following databases are configured:");
                    foreach (Database db in databases)
                    {
                        Console.WriteLine(db.ToString());
                    }

                    Console.WriteLine("");
                }

                //                 0        1         2         3         4         5         6         7
                //                 1234567890123456789012345678901234567890123456789012345678901234567890123456789
                Console.WriteLine("Press ENTER on the database name (blank line) to stop adding databases.");
                Console.WriteLine("");

                Database curr = new Database();
                curr.Name = Common.InputString("Database name?", null, true);

                if (String.IsNullOrEmpty(curr.Name))
                {
                    if (databases.Count < 1)
                    {
                        Console.WriteLine("Error: At least one database must be configured.");
                        Console.WriteLine("");
                        continue;
                    }

                    break;
                }

                string currType = Common.InputString("Database type [mssql|mysql|pgsql]?", "mssql", false);
                if (!currType.Equals("mssql") && !currType.Equals("mysql") && !currType.Equals("pgsql"))
                {
                    Console.WriteLine("Error: Use mssql, mysql, or pgsql for the database type.");
                    Console.WriteLine("");
                    continue;
                }

                curr.Type     = currType;
                curr.Hostname = Common.InputString("Server hostname?", "localhost", false);

                if (curr.Type.Equals("mssql"))
                {
                    curr.Port = Common.InputInteger("Server port?", 1433, true, false);
                }
                else if (curr.Type.Equals("mysql"))
                {
                    curr.Port = Common.InputInteger("Server port?", 3306, true, false);
                }
                else
                {
                    curr.Port = Common.InputInteger("Server port?", 5432, true, false);
                }

                curr.Instance = null;
                if (curr.Type.Equals("mssql"))
                {
                    curr.Instance = Common.InputString("Instance name?", null, true);
                }

                curr.Username = Common.InputString("Username?", null, false);
                curr.Password = Common.InputString("Password?", null, false);
                curr.Debug    = false;
                databases.Add(curr);
            }

            ret.Databases = databases;
            Console.WriteLine("");

            #endregion

            #region Finish

            //                 0        1         2         3         4         5         6         7
            //                 1234567890123456789012345678901234567890123456789012345678901234567890123456789
            Console.WriteLine("All set!  We're writing your configuration to System.Json.  It is important");
            Console.WriteLine("to note that, by default, authentication via API key is **DISABLED**.  You");
            Console.WriteLine("should modify your System.Json file to add API keys to the 'ApiKeys' section.");
            Console.WriteLine("Then, set 'RequireAuthentication' to true in the 'Server' section.");
            Console.WriteLine("Once API keys are added and authentication is set to required, requests will");
            Console.WriteLine("need to be made including the x-api-key header.");
            Console.WriteLine("");

            ret.ToFile("System.Json");

            #endregion
        }
コード例 #3
0
        internal bool Authenticate(HttpContext ctx, out string apiKey, out ApiKey key)
        {
            apiKey = null;
            key    = null;

            #region Extract-API-Key

            apiKey = ctx.Request.RetrieveHeaderValue(_Settings.Server.ApiKeyHeader);
            if (String.IsNullOrEmpty(apiKey))
            {
                _Logging.Warn("Authenticate unable to retrieve API key from headers");
                return(false);
            }

            #endregion

            #region Compare

            if (_Keys != null && _Keys.Count > 0)
            {
                lock (_KeysLock)
                {
                    string tempKey = apiKey;

                    if (_Keys.Exists(k => k.Key.Equals(tempKey)))
                    {
                        ApiKey curr = _Keys.Where(k => k.Key.Equals(tempKey)).First();
                        key = curr;

                        switch (ctx.Request.Method)
                        {
                        case HttpMethod.GET:
                        case HttpMethod.HEAD:
                            return(curr.AllowGet);

                        case HttpMethod.PUT:
                            return(curr.AllowPut);

                        case HttpMethod.POST:
                            return(curr.AllowPost);

                        case HttpMethod.DELETE:
                            return(curr.AllowDelete);

                        default:
                            _Logging.Warn("Authenticate unknown HTTP method " + ctx.Request.Method);
                            return(false);
                        }
                    }
                }

                _Logging.Warn("Authenticate unknown API key " + apiKey);
                return(false);
            }
            else
            {
                _Logging.Warn("Authenticate no API keys defined in configuration");
                return(false);
            }

            #endregion
        }