static void Main(string[] args) { string header = "[Komodo.Server] "; try { _Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); #region Initial-Setup bool initialSetup = false; if (args != null && args.Length >= 1) { if (String.Compare(args[0], "setup") == 0) { initialSetup = true; } } if (!File.Exists("system.json")) { initialSetup = true; } if (initialSetup) { Setup setup = new Setup(); } _Settings = Settings.FromFile("System.json"); #endregion Welcome(initialSetup); InitializeGlobals(); EventWaitHandle waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); bool waitHandleSignal = false; do { waitHandleSignal = waitHandle.WaitOne(1000); } while (!waitHandleSignal); _Logging.Debug(header + "exiting"); } catch (Exception e) { Console.WriteLine(Common.SerializeJson(e, true)); } }
private static async Task GetIndex(RequestMetadata md) { string header = "[Komodo.Server] " + md.Http.Request.Source.IpAddress + ":" + md.Http.Request.Source.Port + " GetIndex "; string indexName = md.Http.Request.Url.Elements[0]; Index index = _Daemon.GetIndex(indexName); if (index == null) { _Logging.Warn(header + "index " + indexName + " does not exist"); md.Http.Response.StatusCode = 404; md.Http.Response.ContentType = "application/json"; await md.Http.Response.Send(new ErrorResponse(404, "Unknown index.", null, null).ToJson(true)); return; } md.Http.Response.StatusCode = 200; md.Http.Response.ContentType = "application/json"; await md.Http.Response.Send(Common.SerializeJson(index, md.Params.Pretty)); return; }
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]"); } }
private void RunSetup() { #region Variables DateTime timestamp = DateTime.UtcNow; Settings settings = new Settings(); #endregion #region Welcome Console.WriteLine( Environment.NewLine + Environment.NewLine + "oooo .o8 " + Environment.NewLine + "`888 888 " + Environment.NewLine + " 888 oooo .ooooo. ooo. .oo. .oo. .ooooo. .oooo888 .ooooo. " + Environment.NewLine + " 888 .8P' d88' `88b `888P'Y88bP'Y88b d88' `88b d88' `888 d88' `88b " + Environment.NewLine + " 888888. 888 888 888 888 888 888 888 888 888 888 888 " + Environment.NewLine + " 888 `88b. 888 888 888 888 888 888 888 888 888 888 888 " + Environment.NewLine + "o888o o888o `Y8bod8P' o888o o888o o888o `Y8bod8P' `Y8bod88P `Y8bod8P' " + Environment.NewLine + Environment.NewLine + Environment.NewLine); // ________________ 1 2 3 4 5 6 7 // ________________12345678901234567890123456789012345678901234567890123456789012345678901234567890 Console.WriteLine("Thank you for using Komodo! We'll put together a basic system configuration"); Console.WriteLine("so you can be up and running quickly."); Console.WriteLine(""); Console.WriteLine(Common.Line(79, "-")); Console.WriteLine(""); #endregion #region Initial-Settings settings.EnableConsole = true; settings.Server = new Settings.ServerSettings(); settings.Server.HeaderApiKey = "x-api-key"; settings.Server.AdminApiKey = "komodoadmin"; settings.Server.ListenerPort = 9090; settings.Server.ListenerHostname = "localhost"; settings.Logging = new Settings.LoggingSettings(); settings.Logging.ConsoleLogging = true; settings.Logging.Header = "komodo"; settings.Logging.SyslogServerIp = "127.0.0.1"; settings.Logging.SyslogServerPort = 514; settings.Logging.MinimumLevel = Severity.Info; settings.Logging.FileLogging = true; settings.Logging.FileDirectory = "./logs/"; settings.Logging.Filename = "Komodo.log"; if (!Directory.Exists("./data/")) { Directory.CreateDirectory("./data/"); } if (!Directory.Exists("./logs/")) { Directory.CreateDirectory("./logs/"); } settings.Database = new DbSettings("./data/komodo.db"); string tempDirectory = "./data/temp/"; settings.TempStorage = new StorageSettings(new DiskSettings(tempDirectory)); if (!Directory.Exists(tempDirectory)) { Directory.CreateDirectory(tempDirectory); } string sourceDirectory = "./data/source/"; settings.SourceDocuments = new StorageSettings(new DiskSettings(sourceDirectory)); if (!Directory.Exists(sourceDirectory)) { Directory.CreateDirectory(sourceDirectory); } string parsedDirectory = "./data/parsed/"; settings.ParsedDocuments = new StorageSettings(new DiskSettings(parsedDirectory)); if (!Directory.Exists(parsedDirectory)) { Directory.CreateDirectory(parsedDirectory); } #endregion #region Initialize-Database-and-Create-Records WatsonORM orm = new WatsonORM(settings.Database.ToDatabaseSettings()); orm.InitializeDatabase(); orm.InitializeTable(typeof(ApiKey)); orm.InitializeTable(typeof(Index)); orm.InitializeTable(typeof(Metadata)); orm.InitializeTable(typeof(MetadataDocument)); orm.InitializeTable(typeof(Node)); orm.InitializeTable(typeof(ParsedDocument)); orm.InitializeTable(typeof(Permission)); orm.InitializeTable(typeof(SourceDocument)); orm.InitializeTable(typeof(TermDoc)); orm.InitializeTable(typeof(TermGuid)); orm.InitializeTable(typeof(User)); DbExpression e = new DbExpression("id", DbOperators.GreaterThan, 0); User user = null; ApiKey apiKey = null; Permission perm = null; Index idx = null; List <User> users = orm.SelectMany <User>(e); if (users == null || users.Count < 1) { Console.WriteLine("| Creating first user 'default'"); user = new User("default", "Default", "*****@*****.**", "default"); user = orm.Insert <User>(user); } else { Console.WriteLine("| Users already exist, not creating default user"); } List <Index> indices = orm.SelectMany <Index>(e); if (indices == null || indices.Count < 1) { Console.WriteLine("| Creating first index 'default'"); idx = new Index(user.GUID, "default"); idx = orm.Insert <Index>(idx); } else { Console.WriteLine("| Indices already exist, not creating default index"); } List <ApiKey> keys = orm.SelectMany <ApiKey>(e); if (keys == null || keys.Count < 1) { Console.WriteLine("| Creating first API key 'default'"); apiKey = new ApiKey("default", user.GUID, true); apiKey = orm.Insert <ApiKey>(apiKey); } else { Console.WriteLine("| API keys already exist, not creating default API key"); } List <Permission> perms = orm.SelectMany <Permission>(e); if (perms == null || perms.Count < 1) { Console.WriteLine("| Creating first permission 'default'"); perm = new Permission(idx.GUID, user.GUID, apiKey.GUID, true, true, true, true, true); perm = orm.Insert <Permission>(perm); } else { Console.WriteLine("| Permissions already exist, not creating default permissions"); } #endregion #region Write-System-JSON File.WriteAllBytes("./system.json", Encoding.UTF8.GetBytes(Common.SerializeJson(settings, true))); #endregion #region Wrap-Up string baseUrl = "http://localhost:" + settings.Server.ListenerPort; // ________________ 1 2 3 4 5 6 7 // ________________12345678901234567890123456789012345678901234567890123456789012345678901234567890 Console.WriteLine(""); Console.WriteLine("All finished!"); Console.WriteLine(""); Console.WriteLine("If you ever want to return to this setup wizard, just re-run the application"); Console.WriteLine("from the terminal with the 'setup' argument."); Console.WriteLine(""); Console.WriteLine("Verify Komodo is running in your browser using the following URL:"); Console.WriteLine(""); Console.WriteLine(" " + baseUrl); Console.WriteLine(""); Console.WriteLine("We've created your first index for you called 'First'. Try POSTing a JSON"); Console.WriteLine("document to the index using the API key 'default' using the URL:"); Console.WriteLine(""); Console.WriteLine(" " + baseUrl + "/default?type=json&name=My+First+Document&x-api-key=default"); Console.WriteLine(""); #endregion }