module api_mapping; import handy_httpd; import handy_httpd.handlers.path_handler; import handy_httpd.handlers.filtered_handler; /** * Defines the Finnow API mapping with a main PathHandler. * Returns: The handler to plug into an HttpServer. */ PathHandler mapApiHandlers() { /// The base path to all API endpoints. const API_PATH = "/api"; PathHandler h = new PathHandler(); // Generic, public endpoints: h.addMapping(Method.GET, API_PATH ~ "/status", &getStatus); h.addMapping(Method.OPTIONS, API_PATH ~ "/**", &getOptions); // Dev endpoint for sample data: REMOVE BEFORE DEPLOYING!!! h.addMapping(Method.POST, API_PATH ~ "/sample-data", &sampleDataEndpoint); // Auth endpoints: import auth.api; h.addMapping(Method.POST, API_PATH ~ "/login", &postLogin); h.addMapping(Method.POST, API_PATH ~ "/register", &postRegister); h.addMapping(Method.GET, API_PATH ~ "/register/username-availability", &getUsernameAvailability); // Authenticated endpoints: PathHandler a = new PathHandler(); a.addMapping(Method.GET, API_PATH ~ "/me", &getMyUser); a.addMapping(Method.DELETE, API_PATH ~ "/me", &deleteMyUser); import profile.api; a.addMapping(Method.GET, API_PATH ~ "/profiles", &handleGetProfiles); a.addMapping(Method.POST, API_PATH ~ "/profiles", &handleCreateNewProfile); /// URL path to a specific profile, with the :profile path parameter. const PROFILE_PATH = API_PATH ~ "/profiles/:profile"; a.addMapping(Method.DELETE, PROFILE_PATH, &handleDeleteProfile); a.addMapping(Method.GET, PROFILE_PATH ~ "/properties", &handleGetProperties); import account.api; a.addMapping(Method.GET, PROFILE_PATH ~ "/accounts", &handleGetAccounts); a.addMapping(Method.POST, PROFILE_PATH ~ "/accounts", &handleCreateAccount); a.addMapping(Method.GET, PROFILE_PATH ~ "/accounts/:accountId:ulong", &handleGetAccount); a.addMapping(Method.DELETE, PROFILE_PATH ~ "/accounts/:accountId:ulong", &handleDeleteAccount); // Protect all authenticated paths with a token filter. import auth.service : TokenAuthenticationFilter, SECRET; HttpRequestFilter tokenAuthenticationFilter = new TokenAuthenticationFilter(SECRET); h.addMapping(API_PATH ~ "/**", new FilteredRequestHandler( a, [tokenAuthenticationFilter] )); return h; } private void getStatus(ref HttpRequestContext ctx) { ctx.response.writeBodyString("online"); } private void getOptions(ref HttpRequestContext ctx) { } private void sampleDataEndpoint(ref HttpRequestContext ctx) { import util.sample_data; import core.thread; Thread t = new Thread(() => generateSampleData()); t.start(); }