Skip to content

Commit

Permalink
docs: update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
wuhan005 committed Nov 29, 2024
1 parent a759f2b commit 6feaff8
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 94 deletions.
33 changes: 12 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Elaina ![Go](https://github.com/wuhan005/Elaina/workflows/Go/badge.svg) [![Go Report Card](https://goreportcard.com/badge/github.com/wuhan005/Elaina)](https://goreportcard.com/report/github.com/wuhan005/Elaina) ![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/wuhan005/elaina) ![Docker Image Version (latest by date)](https://img.shields.io/docker/v/wuhan005/elaina)

<img align="right" src="elaina.gif" width="40%"/>
Docker-based remote code runner.
Container-based remote code runner.

[简体中文](https://github.com/wuhan005/Elaina/blob/master/README_zh.md)

Expand All @@ -10,20 +10,19 @@ Docker-based remote code runner.
### Step 1: Install dependencies

* [Docker](https://docs.docker.com/get-docker/) (v20.10.0 or higher)
* [Postgres](https://www.postgresql.org/download/) (v13.1 or higher)

### Step 2: Pull internal docker images

The [`docker/images/`](https://github.com/wuhan005/Elaina/tree/master/docker/images) folder provides the Dockerfile of
the programming language runtime environment that Elaina supports.

Use `docker pull` command to pull the images from DockerHub before you start running the Elaina. This operation only
needs to be performed once.

```bash
docker pull elainaruntime/golang
docker pull elainaruntime/php
docker pull elainaruntime/python
docker pull elainaruntime/javascript
docker pull glot/php:latest
docker pull glot/python:latest
docker pull glot/golang:latest
docker pull glot/javascript:latest
docker pull glot/c:latest
```

### Step 3: Build and start the Elaina server
Expand All @@ -42,30 +41,22 @@ go build .

#### Set environment variables.

Postgres database configuration.

```bash
export PGPORT=5432
export PGHOST=<REDACTED>
export PGUSER=<REDACTED>
export PGPASSWORD=<REDACTED>
export PGDATABASE=<REDACTED>
export PGSSLMODE=disable
export APP_PASSWORD=<REDACTED>
export RUNTIME_MODE=docker
export POSTGRES_DSN=postgres://postgres:<REDACTED>@127.0.0.1:5432/elaina
```

#### Run the Elaina server.

```bash
# Set the web manager panel password.
export APP_PASSWORD=<REDACTED>

./Elaina
```

### Step 4: Have fun!

Visit `http://<your-host>:8080/m/` to login to the manager panel.
Visit `http://<your-host>:8080/` to login to the manager panel.

## License

MIT
MIT License
33 changes: 12 additions & 21 deletions README_zh.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
# Elaina ![Go](https://github.com/wuhan005/Elaina/workflows/Go/badge.svg) [![Go Report Card](https://goreportcard.com/badge/github.com/wuhan005/Elaina)](https://goreportcard.com/report/github.com/wuhan005/Elaina) ![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/wuhan005/elaina) ![Docker Image Version (latest by date)](https://img.shields.io/docker/v/wuhan005/elaina)

<img align="right" src="elaina.gif" width="40%"/>
基于 Docker 的远程代码运行器
基于容器的远程代码运行器

## 开始使用

### 步骤 1: 安装依赖

* [Docker](https://docs.docker.com/get-docker/) (v20.10.0 或更高)
* [Docker Compose](https://docs.docker.com/compose/install/) (v1.27.4 或更高)
* [Postgres](https://www.postgresql.org/download/) (v13.1 或更高)

### 步骤 2: 拉取内置 Docker 镜像

[`docker/images/`](https://github.com/wuhan005/Elaina/tree/master/docker/images) 文件夹内提供的 Elaina 所支持的编程语言运行环境。

在运行 Elaina 前,请使用 `docker pull` 命令从 DockerHub 拉取这些镜像。该操作只需执行一次即可。

```bash
docker pull elainaruntime/golang
docker pull elainaruntime/php
docker pull elainaruntime/python
docker pull elainaruntime/javascript
docker pull glot/php:latest
docker pull glot/python:latest
docker pull glot/golang:latest
docker pull glot/javascript:latest
docker pull glot/c:latest
```

### Step 3: 编译并启动 Elaina
Expand All @@ -39,30 +38,22 @@ go build .

#### 设置环境变量

Postgres 数据库配置。

```bash
export PGPORT=5432
export PGHOST=<REDACTED>
export PGUSER=<REDACTED>
export PGPASSWORD=<REDACTED>
export PGDATABASE=<REDACTED>
export PGSSLMODE=disable
export APP_PASSWORD=<REDACTED>
export RUNTIME_MODE=docker
export POSTGRES_DSN=postgres://postgres:<REDACTED>@127.0.0.1:5432/elaina
```

#### 运行 Elaina

```bash
# 设置 Web 管理面板的密码
export APP_PASSWORD=<REDACTED>

./Elaina
```

### 步骤 4: 走你!

浏览器访问 `http://<your-host>:8080/m/` 来登录管理员面板。
浏览器访问 `http://<your-host>:8080/` 来登录管理员面板。

## 开源协议

MIT
MIT License
59 changes: 7 additions & 52 deletions internal/form/form.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,81 +10,36 @@ import (
"reflect"

"github.com/flamego/flamego"
"github.com/sirupsen/logrus"
"github.com/wuhan005/govalid"
"golang.org/x/text/language"
)

type ErrorCategory string

const (
ErrorCategoryDeserialization ErrorCategory = "deserialization"
ErrorCategoryValidation ErrorCategory = "validation"
"github.com/wuhan005/Elaina/internal/context"
)

type Error struct {
Category ErrorCategory
Error error
}

func Bind(model interface{}) flamego.Handler {
// Ensure not pointer.
if reflect.TypeOf(model).Kind() == reflect.Ptr {
panic("form: pointer can not be accepted as binding model")
}

return flamego.ContextInvoker(func(c flamego.Context) {
return func(ctx context.Context) {
obj := reflect.New(reflect.TypeOf(model))
r := c.Request().Request
r := ctx.Request().Request
if r.Body != nil {
defer func() { _ = r.Body.Close() }()

if err := json.NewDecoder(r.Body).Decode(obj.Interface()); err != nil {
c.Map(Error{Category: ErrorCategoryDeserialization, Error: err})
if _, err := c.Invoke(errorHandler); err != nil {
panic("form: " + err.Error())
}
_ = ctx.Error(http.StatusBadRequest, "Failed to parse request body")
return
}
}

acceptLanguage := r.Header.Get("Accept-Language")
languageTags, _, _ := language.ParseAcceptLanguage(acceptLanguage)
languageTag := language.Chinese
if len(languageTags) > 0 {
languageTag = languageTags[0]
}

errors, ok := govalid.Check(obj.Interface(), languageTag)
errors, ok := govalid.Check(obj.Interface())
if !ok {
c.Map(Error{Category: ErrorCategoryValidation, Error: errors[0]})
if _, err := c.Invoke(errorHandler); err != nil {
panic("form: " + err.Error())
}
_ = ctx.Error(http.StatusBadRequest, errors[0].Error())
return
}

// Validation passed.
c.Map(obj.Elem().Interface())
})
}

func errorHandler(c flamego.Context, error Error) {
c.ResponseWriter().WriteHeader(http.StatusBadRequest)
c.ResponseWriter().Header().Set("Content-Type", "application/json; charset=utf-8")

var msg string
if error.Category == ErrorCategoryDeserialization {
msg = "invalid request body"
} else {
msg = error.Error.Error()
}

body := map[string]interface{}{
"msg": msg,
}
err := json.NewEncoder(c.ResponseWriter()).Encode(body)
if err != nil {
logrus.WithError(err).Error("Failed to encode response")
ctx.Map(obj.Elem().Interface())
}
}

0 comments on commit 6feaff8

Please sign in to comment.