improve error handling, limit upload size
This commit is contained in:
parent
ef0d33aac4
commit
4ceec30e0c
2 changed files with 66 additions and 25 deletions
|
@ -19,34 +19,66 @@ public class ImageHandler {
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final Storage storage;
|
private final Storage storage;
|
||||||
private final TemporalAmount expireTime;
|
private final TemporalAmount expireTime;
|
||||||
|
private final int maxImageSize;
|
||||||
|
|
||||||
public ImageHandler(Logger logger, Storage storage, TemporalAmount expireTime) {
|
public ImageHandler(Logger logger, Storage storage, TemporalAmount expireTime, int maxImageSize) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
this.expireTime = expireTime;
|
this.expireTime = expireTime;
|
||||||
|
this.maxImageSize = maxImageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void uploadImage(Context ctx) throws IOException {
|
public void uploadImage(Context ctx) {
|
||||||
|
try {
|
||||||
InputStream body = ctx.bodyInputStream();
|
InputStream body = ctx.bodyInputStream();
|
||||||
BufferedImage image = Imaging.getBufferedImage(body);
|
BufferedImage image = Imaging.getBufferedImage(body);
|
||||||
|
|
||||||
byte[] png = Imaging.writeImageToBytes(image, ImageFormats.PNG);
|
byte[] png = Imaging.writeImageToBytes(image, ImageFormats.PNG);
|
||||||
|
if (png.length > maxImageSize) {
|
||||||
|
ctx
|
||||||
|
.status(HttpStatus.CONTENT_TOO_LARGE)
|
||||||
|
.result("Image too large");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Instant expiresAt = Instant.now().plus(this.expireTime);
|
Instant expiresAt = Instant.now().plus(this.expireTime);
|
||||||
|
|
||||||
String id = storage.put(png, expiresAt);
|
String id = storage.put(png, expiresAt);
|
||||||
logger.info("Stored {} bytes as {}", png.length, id);
|
logger.info("Uploaded {} image bytes as {}", png.length, id);
|
||||||
|
|
||||||
ctx.
|
ctx.
|
||||||
status(HttpStatus.CREATED).
|
status(HttpStatus.CREATED).
|
||||||
contentType(ContentType.TEXT_PLAIN).
|
contentType(ContentType.TEXT_PLAIN).
|
||||||
result(id);
|
result(id);
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
ctx
|
||||||
|
.status(HttpStatus.BAD_REQUEST)
|
||||||
|
.result("Unrecognized image format");
|
||||||
|
} catch (IOException e) {
|
||||||
|
ctx
|
||||||
|
.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
.result("Internal Server Error");
|
||||||
|
|
||||||
|
this.logger.error("Failed to upload image", e);
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
ctx
|
||||||
|
.status(HttpStatus.INSUFFICIENT_STORAGE)
|
||||||
|
.result("Insufficient storage on server");
|
||||||
|
|
||||||
|
this.logger.error("Out of memory", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void downloadImage(Context ctx) throws IOException {
|
public void downloadImage(Context ctx) {
|
||||||
|
try {
|
||||||
String id = ctx.pathParam("id");
|
String id = ctx.pathParam("id");
|
||||||
byte[] png = storage.get(id);
|
byte[] png = storage.get(id);
|
||||||
if (png == null) {
|
if (png == null) {
|
||||||
ctx.status(HttpStatus.NOT_FOUND);
|
ctx
|
||||||
|
.status(HttpStatus.NOT_FOUND)
|
||||||
|
.result("Image not found");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,5 +86,12 @@ public class ImageHandler {
|
||||||
status(HttpStatus.OK).
|
status(HttpStatus.OK).
|
||||||
contentType(ContentType.IMAGE_PNG).
|
contentType(ContentType.IMAGE_PNG).
|
||||||
result(png);
|
result(png);
|
||||||
|
} catch (IOException e) {
|
||||||
|
ctx
|
||||||
|
.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
.result("Internal Server Error");
|
||||||
|
|
||||||
|
this.logger.error("Failed to download image", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,17 @@ public class Main {
|
||||||
new MemoryStorage(),
|
new MemoryStorage(),
|
||||||
Duration.ofSeconds(5),
|
Duration.ofSeconds(5),
|
||||||
Duration.ofMinutes(2),
|
Duration.ofMinutes(2),
|
||||||
|
16 * 1024 * 1024, // 16 MiB
|
||||||
3000
|
3000
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void run(Logger logger, Storage storage, Duration clearTime, TemporalAmount expireTime, int port) {
|
private static void run(Logger logger, Storage storage, Duration clearTime, TemporalAmount expireTime, int maxImageSize, int port) {
|
||||||
ImageHandler handler = new ImageHandler(
|
ImageHandler handler = new ImageHandler(
|
||||||
logger,
|
logger,
|
||||||
storage,
|
storage,
|
||||||
expireTime
|
expireTime,
|
||||||
|
maxImageSize
|
||||||
);
|
);
|
||||||
|
|
||||||
Thread.ofVirtual().start(() -> {
|
Thread.ofVirtual().start(() -> {
|
||||||
|
|
Loading…
Reference in a new issue