Skip to content

Commit 74d6aec

Browse files
committed
added openapi docs for eval api
1 parent ce2c90a commit 74d6aec

File tree

3 files changed

+73
-30
lines changed

3 files changed

+73
-30
lines changed

JShellAPI/build.gradle

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@ import java.time.Instant
22

33
plugins {
44
id 'org.springframework.boot' version '3.2.5'
5-
id 'io.spring.dependency-management' version '1.1.5'
6-
id 'com.google.cloud.tools.jib' version '3.4.2'
5+
id 'io.spring.dependency-management' version '1.1.0'
6+
id 'org.springdoc.openapi-gradle-plugin' version '1.8.0'
7+
id 'com.google.cloud.tools.jib' version '3.3.2'
78
id 'com.github.johnrengelman.shadow' version '8.1.1'
89
}
910

1011
dependencies {
1112
implementation project(':JShellWrapper')
1213
implementation 'org.springframework.boot:spring-boot-starter-web'
14+
implementation 'org.springframework.boot:spring-boot-starter-validation'
1315
implementation 'com.github.docker-java:docker-java-transport-httpclient5:3.3.6'
1416
implementation 'com.github.docker-java:docker-java-core:3.3.6'
1517

18+
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0'
19+
implementation 'org.springdoc:springdoc-openapi-starter-webflux-ui:2.5.0'
20+
1621
testImplementation 'org.springframework.boot:spring-boot-starter-test'
1722
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
1823
}

JShellAPI/src/main/java/org/togetherjava/jshellapi/rest/JShellController.java

+65-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
package org.togetherjava.jshellapi.rest;
22

3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.Parameter;
5+
import io.swagger.v3.oas.annotations.media.Content;
6+
import io.swagger.v3.oas.annotations.media.ExampleObject;
7+
import io.swagger.v3.oas.annotations.media.Schema;
8+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
9+
10+
import jakarta.validation.constraints.Pattern;
11+
312
import org.springframework.beans.factory.annotation.Autowired;
413
import org.springframework.http.HttpStatus;
514
import org.springframework.web.bind.annotation.*;
@@ -17,16 +26,52 @@
1726
@RequestMapping("jshell")
1827
@RestController
1928
public class JShellController {
20-
private JShellSessionService service;
21-
private StartupScriptsService startupScriptsService;
29+
private static final String ID_REGEX = "^[a-zA-Z0-9][a-zA-Z0-9_.-]+$";
30+
31+
@Autowired private JShellSessionService service;
32+
@Autowired private StartupScriptsService startupScriptsService;
2233

2334
@PostMapping("/eval/{id}")
35+
@Operation(
36+
summary = "Evaluate code in a JShell session",
37+
description =
38+
"Evaluate code in a JShell session, create a session from this id, or use an"
39+
+ " existing session if this id already exists.")
40+
@ApiResponse(
41+
responseCode = "200",
42+
content = {
43+
@Content(
44+
mediaType = "application/json",
45+
schema = @Schema(implementation = JShellResult.class))
46+
})
2447
public JShellResult eval(
25-
@PathVariable String id,
26-
@RequestParam(required = false) StartupScriptId startupScriptId,
27-
@RequestBody String code)
48+
@Parameter(description = "id of the session, must follow the regex " + ID_REGEX)
49+
@Pattern(regexp = ID_REGEX, message = "'id' doesn't match regex " + ID_REGEX)
50+
@PathVariable
51+
String id,
52+
@Parameter(description = "id of the startup script to use")
53+
@RequestParam(required = false)
54+
StartupScriptId startupScriptId,
55+
@io.swagger.v3.oas.annotations.parameters.RequestBody(
56+
content = {
57+
@Content(
58+
mediaType = "text/plain",
59+
examples = {
60+
@ExampleObject(
61+
name = "Hello world example",
62+
value =
63+
"System.out.println(\"Hello,"
64+
+ " World!\");"),
65+
@ExampleObject(
66+
name =
67+
"Hello world example with startup"
68+
+ " script",
69+
value = "println(\"Hello, World!\");")
70+
})
71+
})
72+
@RequestBody
73+
String code)
2874
throws DockerException {
29-
validateId(id);
3075
return service.session(id, startupScriptId)
3176
.eval(code)
3277
.orElseThrow(
@@ -68,11 +113,12 @@ public JShellResult singleEval(
68113

69114
@GetMapping("/snippets/{id}")
70115
public List<String> snippets(
71-
@PathVariable String id, @RequestParam(required = false) boolean includeStartupScript)
116+
@PathVariable
117+
@Pattern(regexp = ID_REGEX, message = "'id' doesn't match regex " + ID_REGEX)
118+
String id,
119+
@RequestParam(required = false) boolean includeStartupScript)
72120
throws DockerException {
73-
validateId(id);
74-
if (!service.hasSession(id))
75-
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Id " + id + " not found");
121+
checkId(id);
76122
return service.session(id, null)
77123
.snippets(includeStartupScript)
78124
.orElseThrow(
@@ -82,10 +128,12 @@ public List<String> snippets(
82128
}
83129

84130
@DeleteMapping("/{id}")
85-
public void delete(@PathVariable String id) throws DockerException {
86-
validateId(id);
87-
if (!service.hasSession(id))
88-
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Id " + id + " not found");
131+
public void delete(
132+
@PathVariable
133+
@Pattern(regexp = ID_REGEX, message = "'id' doesn't match regex " + ID_REGEX)
134+
String id)
135+
throws DockerException {
136+
checkId(id);
89137
service.deleteSession(id);
90138
}
91139

@@ -94,21 +142,10 @@ public String startupScript(@PathVariable StartupScriptId id) {
94142
return startupScriptsService.get(id);
95143
}
96144

97-
@Autowired
98-
public void setService(JShellSessionService service) {
99-
this.service = service;
100-
}
101-
102-
@Autowired
103-
public void setStartupScriptsService(StartupScriptsService startupScriptsService) {
104-
this.startupScriptsService = startupScriptsService;
105-
}
106-
107-
private static void validateId(String id) throws ResponseStatusException {
108-
if (!id.matches("[a-zA-Z0-9][a-zA-Z0-9_.-]+")) {
145+
private void checkId(String id) {
146+
if (!id.matches(ID_REGEX)) {
109147
throw new ResponseStatusException(
110-
HttpStatus.BAD_REQUEST,
111-
"Id " + id + " doesn't match the regex [a-zA-Z0-9][a-zA-Z0-9_.-]+");
148+
HttpStatus.BAD_REQUEST, "Id " + id + " doesn't match regex " + ID_REGEX);
112149
}
113150
}
114151
}

JShellAPI/src/main/resources/application.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jshellapi:
2323
server:
2424
error:
2525
include-message: always
26+
include-binding-errors: always
2627

2728
logging:
2829
level:

0 commit comments

Comments
 (0)