API REST do Jobe
O Jobe é o servidor que compila e executa código num sandbox. O CodeRunner usa a API do Jobe por baixo dos panos, mas você pode chamá-la diretamente — para testar o sandbox, depurar a integração com o Moodle ou construir um corretor próprio que roda código do aluno.
- URL base:
http(s)://SEU-JOBE/jobe/index.php/restapi/ - Formato: JSON (envie
Content-Type: application/json). - Modo imediato: o resultado da execução volta na resposta do POST (o Jobe não guarda o run;
GET runs/{id}sempre dá 404, a menos quedebugsejatrue).
restapiO segmento restapi aparece em todos os endpoints — inclusive runs e files. Ex.: POST /jobe/index.php/restapi/runs.
Referência rápida
| Método | Endpoint | Descrição |
|---|---|---|
GET | /jobe/index.php/restapi/languages | Lista linguagens e versões suportadas |
POST | /jobe/index.php/restapi/runs | Submete um job para execução |
PUT | /jobe/index.php/restapi/files/{id} | Envia um arquivo de apoio |
GET / HEAD | /jobe/index.php/restapi/files/{id} | Verifica se um arquivo existe |
Autenticação
Se o seu Jobe exigir chave, envie o cabeçalho X-API-KEY: SUA-CHAVE em cada requisição. A API também responde com cabeçalhos CORS (GET, POST, OPTIONS, PUT, HEAD, DELETE).
GET languages — linguagens suportadas
curl -s http://localhost:4000/jobe/index.php/restapi/languages
Resposta (200 OK): uma lista de pares [id, versao].
[
["c", "gcc 11.4.0"],
["cpp", "g++ 11.4.0"],
["python3", "3.10.12"],
["java", "17.0.10"],
["pascal", "3.2.2"],
["php", "8.1"]
]
O primeiro elemento de cada par é o language_id que você usa no run_spec. É o teste mais rápido para confirmar que o Jobe está no ar.
POST runs — executar código
O corpo é um objeto com a chave run_spec:
| Campo | Obrig.? | Descrição |
|---|---|---|
language_id | sim | "c", "cpp", "python3", … |
sourcecode | sim | o código-fonte (string) |
sourcefilename | não | nome do arquivo-fonte (o Jobe infere se você omitir) |
input | não | dados enviados ao stdin do programa |
file_list | não | arquivos de apoio: [[id, nome], …] (ver seção de arquivos) |
parameters | não | limites de execução (cputime, memorylimit, …), dependem da instalação |
debug | não | se true, o run é preservado no servidor (não recomendado em produção) |
- Python (com stdin)
- C (com stdin)
- Python (requests) — recomendado
curl -s http://localhost:4000/jobe/index.php/restapi/runs \
-H "Content-Type: application/json" \
-d '{
"run_spec": {
"language_id": "python3",
"sourcecode": "print(sum(int(x) for x in input().split()))",
"input": "3 4 5\n"
}
}'
Resposta:
{ "run_id": null, "outcome": 15, "cmpinfo": "", "stdout": "12\n", "stderr": "" }
curl -s http://localhost:4000/jobe/index.php/restapi/runs \
-H "Content-Type: application/json" \
-d '{
"run_spec": {
"language_id": "c",
"sourcecode": "#include <stdio.h>\nint main(){int a,b;scanf(\"%d %d\",&a,&b);printf(\"%d\\n\",a+b);return 0;}",
"input": "20 22\n"
}
}'
Resposta: outcome 15 e stdout "42\n".
Montar JSON com código-fonte à mão vira um inferno de escape (\n, aspas). Na prática, use uma biblioteca:
import requests
resp = requests.post(
"http://localhost:4000/jobe/index.php/restapi/runs",
headers={"X-API-KEY": "SUA-CHAVE"}, # se configurado
json={"run_spec": {
"language_id": "c",
"sourcecode": open("solucao.c").read(),
"input": "20 22\n",
}},
timeout=30,
)
r = resp.json()
print("outcome:", r["outcome"])
print("stdout :", r["stdout"])
print("cmpinfo:", r["cmpinfo"]) # erros de compilacao aparecem aqui
O resultado (run_result)
| Campo | Descrição |
|---|---|
outcome | código numérico do desfecho (tabela abaixo) |
cmpinfo | saída do compilador — erros de compilação vêm aqui, não em stderr |
stdout | saída padrão do programa |
stderr | saída de erro do programa |
run_id | null no modo imediato |
Códigos de outcome
| Código | Significado |
|---|---|
| 15 | OK — compilou e rodou |
| 11 | Erro de compilação (veja cmpinfo) |
| 12 | Erro em tempo de execução |
| 13 | Tempo limite excedido |
| 17 | Memória excedida |
| 19 | Chamada de sistema proibida (violou o sandbox) |
| 20 | Erro interno do Jobe |
| 21 | Servidor sobrecarregado |
Um teste "passou" quando outcome == 15 e o stdout bate com o esperado. Se outcome == 11, mostre o cmpinfo ao aluno (é a mensagem do compilador).
Arquivos de apoio (files)
Alguns exercícios precisam de arquivos extras (um .h, um dataset). O fluxo é: enviar o arquivo uma vez e depois referenciá-lo no run_spec via file_list.
- O
{id}do arquivo é, por convenção, o MD5 do conteúdo. - O corpo do
PUTtraz o conteúdo em base64 no campofile_contents. - Só PUT é suportado para enviar (não POST).
Enviar um arquivo:
ARQ=dados.txt
ID=$(md5sum "$ARQ" | cut -d' ' -f1)
B64=$(base64 -w0 "$ARQ")
curl -s -X PUT "http://localhost:4000/jobe/index.php/restapi/files/$ID" \
-H "Content-Type: application/json" \
-d "{\"file_contents\": \"$B64\"}"
# 204 No Content = enviado com sucesso
Verificar se existe (HEAD ou GET):
curl -s -I "http://localhost:4000/jobe/index.php/restapi/files/$ID"
# 204 = existe | 404 = nao existe
Usar no run (o arquivo aparece com o nome dado, no diretório de trabalho):
{
"run_spec": {
"language_id": "c",
"sourcecode": "... abre e le dados.txt ...",
"file_list": [["COLE-O-ID-AQUI", "dados.txt"]]
}
}
Se um id referenciado não existir, o run falha com 404 e a mensagem "One or more of the specified files is missing/unavailable".
Erros comuns
| Situação | Resposta |
|---|---|
Faltou language_id | 400 — "run_spec is missing the required attribute 'language_id'" |
Faltou sourcecode | 400 — "run_spec is missing the required attribute 'sourcecode'" |
file_list cita id inexistente | 404 — arquivo ausente |
GET /runs/{id} (buscar run) | 404 — runs não são guardados no modo imediato |
Testar rápido com jobeinabox
Sem instalar nada além do Docker:
docker run -d --name jobe -p 4000:80 trampgeek/jobeinabox:latest
curl -s http://localhost:4000/jobe/index.php/restapi/languages
Se a lista de linguagens voltar, o Jobe está pronto para receber runs.
Como isso conecta ao curso
- Depuração: se o CodeRunner falhar no Moodle, um
curldelanguagese umrunssimples isolam o problema (é o Jobe ou é o Moodle?). - Corretor próprio: o
grade.pydeste curso poderia ganhar um check que executa o código do aluno no Jobe (POSTruns) e comparastdout— indo além docontem/compila, sem instalar compiladores no runner de CI. - Ferramenta de estudo: um pequeno script que manda o código para o Jobe e mostra
outcome/stdoutdá ao aluno o mesmo feedback do CodeRunner fora do Moodle.
Para criar as questões no Moodle em cima deste sandbox, veja o guia Moodle + CodeRunner.
Referência — API REST do Jobe.