> This page is for Applications Protection.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.humansecurity.com/llms.txt.

# Installing the Enforcer

## Installing the GO Enforcer

The GO Enforcer is used as a middleware inside a GO web application.\
Implementation steps:

1. Import the HUMAN package.
2. Implement the Runtime interface.
3. Implement the Enforcer.

### Import the HUMAN package

```shell
go get github.com/perimeterx/perimeterx-go-sdk/perimeterx
```

> **GitHub Repository Access**
>
> If you do not have access the Go SDK GitHub Repository, please reach out to our Customer Support team.

### Implement the Runtime interface

The implementation consist of the Runtime methods:

```go
type Runtime interface {
    GetConfig() PxConfig
    PerformSyncRequest(*http.Request, int) (*http.Response, error)
    PerformAsyncRequest(*http.Request, int)
    Log(message string)
    GetOS() string
    GetHostName() string
}
```

#### GetConfig - Create configuration map.

* Return HUMANConfig
* The Configuration fields should be set according to the **Configuration Options** section.
* The HUMAN**Application ID / AppId** and HUMAN**Token / Auth Token** can be found in the Portal, under [Applications](https://console.perimeterx.com/botDefender/applications) section.
* The HUMAN**Cookie Encryption Key** can be found in the portal, under [Policies](https://console.perimeterx.com/botDefender/policies) section.
* The Policy from where the **Cookie Encryption Key** is taken must correspond with the Application from where the **Application ID / AppId** and HUMAN**Token / Auth Token**

#### PerformSyncRequest - perform synchronous request.

* Return: response \*http.Response, error.
* Arguments: request \*http.Request, timeout int.

#### PerformAsyncRequest - perform asynchronous request.

* Arguments: request \*http.Request, timeout int.
* **It is the caller's responsibility to close the body**.

#### Log - Logging implementation.

* Argument: message string.

#### GetOS - get the Operating System name.

* Return: name string.

#### GetHostName - get the host name.

* Return: name string.

### Implement the Enforcer

* The enforcer is the main function of the module.
* It enforces the request using the runtime instance as a context and can return a blocking response or an error.
* In case the response is empty, the request should be forward to the origin.
* Errors are silent.
* In addition the enforcer handles HUMAN activities.

Example:

```go
import (
  "github.com/perimeterx/perimeterx-go-sdk/perimeterx"
)

type Adapter func(http.Handler) http.Handler

var pxConfig perimeterx.PxConfig

func main() {
    log.Printf("Go Server is running on port %d, %s OS with an %s CPU.", port, goruntime.GOOS, goruntime.GOARCH)

    pxConfig = *NewPXConfigBuilder("App ID", "Cookie Secret", "Auth Token").
        SetMonitorMode("active_blocking").
        Build()

    http.Handle("/", middleware()(http.FileServer(http.Dir("./static"))))
    http.ListenAndServe(":3000", nil)
}

func middleware() Adapter {
    return func(h http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            responseWriter := perimeterx.NewResponseWriterWrapper(w)
            response, context, err := perimeterx.Enforce(r, &ExampleRuntime{})

            fmt.Print(context.Score)

            if err != nil {
                fmt.Print(err)
            }

            if response.Body != nil {
                responseWriter.WriteHeader(response.StatusCode)
                responseWriter.Header().Set("Content-Type", response.Header.Get("Content-Type"))
                var body, _ = ioutil.ReadAll(response.Body)
                responseWriter.Write(body)
            } else {
                h.ServeHTTP(responseWriter, r)
            }
        })
    }
}

var tr = &http.Transport{
    MaxIdleConnsPerHost:   10,
    ResponseHeaderTimeout: 60 * time.Second,
}
var client = &http.Client{Transport: tr}

type ExampleRuntime struct {
}

func (runtime *ExampleRuntime) GetConfig() perimeterx.PxConfig {
    return pxConfig
}

func (runtime *ExampleRuntime) PerformSyncRequest(req *http.Request, timeout int) (*http.Response, error) {
    client.Timeout = time.Duration(timeout) * time.Millisecond
    return client.Do(req)
}

func (runtime *ExampleRuntime) PerformAsyncRequest(req *http.Request, timeout int) {
    go runtime.PerformSyncRequest(req, timeout)
}

func (runtime *ExampleRuntime) GetOS() string {
    return goruntime.GOOS
}

func (runtime *ExampleRuntime) GetHostName() string {
    osName, _ := os.Hostname()
    return osName
}

func (runtime *ExampleRuntime) Log(message string) {
    fmt.Print(message)
}
```