# HTTP Server

## Overview

The HTTP server serves as the entry point for Diarkis. The application server connects to the HTTP server to obtain real-time connection endpoints and encryption keys.

Additionally, you can define custom endpoints.

## Setting Up the HTTP Server

To expose built-in commands to the client, you can set it up using the `diarkisexec` package.

* You can expose built-in commands by specifying modules with `diarkisexec.SetupDiarkis()`. By setting `ConfigPath` for each module, you can customize the configuration.
* You can expose custom commands using `diarkisexec.SetServerCommandHandler()`.
* You can set up a UDP server with `diarkisexec.SetupDiarkisHTTPServer()`. You can customize the server settings using a JSON file as an argument.

> :warning: The above functions must be executed before calling `diarkisexec.StartDiarkis()`.

For more details, please refer to the [API reference of diarkisexec](https://docs.diarkis.io/docs/server/current/diarkis/diarkisexec/index.html).

```go
package main

import (
	"github.com/Diarkis/diarkis/diarkisexec"

	"github.com/Diarkis/diarkis-server-template/cmds"
)

func main() {
	logConfigPath := "/configs/shared/log.json"
	meshConfigPath := "/configs/shared/mesh.json"

	diarkisexec.SetupDiarkis(logConfigPath, meshConfigPath, &diarkisexec.Modules{
		Dive:       &diarkisexec.Options{ConfigPath: "/configs/shared/dive.json", ExposeCommands: true},
		Field:      &diarkisexec.Options{ConfigPath: "/configs/shared/field.json", ExposeCommands: true},
		DM:         &diarkisexec.Options{ConfigPath: "/configs/shared/dm.json", ExposeCommands: true},
		MatchMaker: &diarkisexec.Options{ConfigPath: "/configs/shared/matching.json", ExposeCommands: true},
	})

	httpcmds.SetupHTTP()

	diarkisexec.SetupDiarkisHTTPServer("/configs/http/main.json")

	diarkisexec.StartDiarkis()
}
```

## Mesh Configuration

Specify the path to the JSON file in `meshConfigPath`. For more details, refer to [#mesh-setup](#mesh-setup "mention").

## HTTP Server Configuration

Configuration is done in JSON format.

<table><thead><tr><th width="230">Key</th><th width="119">Default</th><th></th></tr></thead><tbody><tr><td>address</td><td>"127.0.0.1"</td><td>The address for binding the UDP server</td></tr><tr><td>port</td><td>"7000"</td><td>The port for the UDP server to bind to. The UDP server will automatically search for an available port starting from the specified port.</td></tr><tr><td>useFixedPort</td><td>false</td><td>If set to true, the HTTP server will bind only to the specified port.</td></tr><tr><td>timeout</td><td>5</td><td>HTTP response timeout (seconds)</td></tr><tr><td>enableEncryption</td><td>true</td><td>If set to false, packet encryption and decryption will be disabled. Other servers need to be configured similarly.</td></tr></tbody></table>

For more details, please refer to the [API reference for http](https://docs.diarkis.io/docs/server/current/diarkis/server/http/index.html).

## **Creating Custom HTTP Endpoints**

Diarkis's HTTP server allows you to write custom endpoints.

```go
package httpcmds

import (
      "github.com/Diarkis/diarkis/server/http"
)

func Expose(rootpath string) {
      // :message is treated as a parameter and the value can be accessed from *http.Params

      http.Get("/hello/:message", handleHello)
}

func handleHello(res *http.Response, req *http.Request, params *http.Params, next func(error)) {
      message := params.GetAsString("message")
      res.Respond(message, http.Ok)
      // move on to other handlers
      next(nil)
}

```

### Using JSON in HTTP Endpoints

Diarkis's HTTP server automatically decodes the request body into `req.JSONBody` when the ContentType of the request is `application/json`. Note that an object must be described to store in the JSON Body.

```go
package httpcmds

import (
	"github.com/Diarkis/diarkis/server/http"
)

func Expose(rootpath string) {
	http.Post("/echo", handleEcho)
}

func handleEcho(res *http.Response, req *http.Request, params *http.Params, next func(error)) {
	if req.JSONBody == nil {
		err := errors.New("expect JSON body")
		res.Respond(err.Error(), http.Bad)
		next(err)
		return
	}

	message, ok := req.JSONBody["message"].(string)
	if !ok {
		err := errors.New("missing parameter message")
		res.Respond(err.Error(), http.Bad)
		next(err)
		return
	}

	enc, err := json.Marshal(map[string]any{"echo": message})
	if err != nil {
		res.Respond(err.Error(), http.Bad)
		next(err)
		return
	}

	res.SetHeader("Content-Type", "application/json")
	res.SendBytes(enc, http.Ok)
	// move on to other handlers
	next(nil)
}
```
