/*
|
neon - Embeddable HTTP Server based on jdk.httpserver
|
Copyright (C) 2024 Ulrich Hilger
|
|
This program is free software: you can redistribute it and/or modify
|
it under the terms of the GNU Affero General Public License as
|
published by the Free Software Foundation, either version 3 of the
|
License, or (at your option) any later version.
|
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU Affero General Public License for more details.
|
|
You should have received a copy of the GNU Affero General Public License
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
*/
|
package de.uhilger.neon;
|
|
import com.sun.net.httpserver.Headers;
|
import com.sun.net.httpserver.HttpExchange;
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.io.OutputStream;
|
import java.nio.file.Files;
|
import java.text.SimpleDateFormat;
|
import java.util.Date;
|
|
/**
|
* Helfer zur Beantwortung von HTTP-Anfragen
|
*
|
* @author Ulrich Hilger
|
* @version 1, 03.06.2021
|
*/
|
public class HttpResponder {
|
|
/* Headernamen */
|
public static final String ACCEPT_RANGES_HEADER = "Accept-Ranges";
|
public static final String CONTENT_LENGTH = "Content-Length";
|
public static final String CONTENT_TYPE = "Content-Type";
|
public static final String LAST_MODIFIED_DATE_HEADER = "Last-Modified";
|
|
/* Statuscodes */
|
public static final int SC_OK = 200;
|
public static final int SC_NOT_FOUND = 404;
|
public static final int SC_METHOD_NOT_ALLOWED = 405;
|
public static final int SC_UNPROCESSABLE_ENTITY = 422;
|
public static final int SC_INTERNAL_SERVER_ERROR = 500;
|
|
/* String Konstanten */
|
public static final String STR_BYTES = "bytes";
|
public static final String STR_NOT_FOUND = " not found.";
|
public static final String LM_PATTERN = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
|
/**
|
* Den Inhalt einer Datei ausliefern
|
*
|
* @param e das Objekt mit Methoden zur Untersuchung der Anfrage sowie zum
|
* Anfertigen und Senden der Antwort
|
* @param file die Datei, deren Inhalt ausgeliefert werden soll
|
* @throws IOException falls etwas schief geht entsteht dieser Fehler
|
*/
|
public void serveFile(HttpExchange e, File file) throws IOException {
|
if (file.exists()) {
|
setHeaders(e, file);
|
e.getResponseHeaders().set(CONTENT_LENGTH, Long.toString(file.length()));
|
e.sendResponseHeaders(SC_OK, file.length());
|
if(HttpHelper.HTTP_GET.equalsIgnoreCase(e.getRequestMethod())) {
|
InputStream in = new FileInputStream(file);
|
OutputStream os = e.getResponseBody();
|
write(in, os);
|
finish(in, os);
|
}
|
} else {
|
sendNotFound(e, file.getName());
|
}
|
}
|
|
public void write(InputStream in, OutputStream out) throws IOException {
|
byte[] b = new byte[4096];
|
int bytesRead = in.read(b);
|
while (bytesRead > -1) {
|
out.write(b, 0, bytesRead);
|
bytesRead = in.read(b);
|
}
|
}
|
|
public void finish(InputStream in, OutputStream out) throws IOException {
|
in.close();
|
finish(out);
|
}
|
|
public void finish(OutputStream out) throws IOException {
|
out.flush();
|
out.close();
|
}
|
|
/**
|
* Die Header erzeugen, die unabhängig davon, ob der ganze
|
* Inhalt oder nur Teile davon ausgeliefert werden sollen, in der
|
* Antwort stehen sollen
|
*
|
* @param e das Objekt mit Methoden zur Untersuchung der Anfrage sowie zum
|
* Anfertigen und Senden der Antwort
|
* @param file die Datei, für die die Header gelten
|
* @throws IOException falls etwas schief geht entsteht dieser Fehler
|
*/
|
public void setHeaders(HttpExchange e, File file) throws IOException {
|
Headers resHeaders = e.getResponseHeaders();
|
resHeaders.add(ACCEPT_RANGES_HEADER, STR_BYTES);
|
String mimeType = Files.probeContentType(file.toPath());
|
if (mimeType != null) {
|
resHeaders.add(CONTENT_TYPE, mimeType);
|
}
|
SimpleDateFormat sdf = new SimpleDateFormat(LM_PATTERN);
|
Date date = new Date(file.lastModified());
|
resHeaders.add(LAST_MODIFIED_DATE_HEADER, sdf.format(date));
|
}
|
|
/**
|
* Eine nicht gefunden Antwort senden
|
*
|
* @param e das Objekt mit Methoden zur Untersuchung der Anfrage sowie zum
|
* Anfertigen und Senden der Antwort
|
* @param fname Name der Datei, die nicht gefunden wurde
|
* @throws IOException falls etwas schief geht entsteht dieser Fehler
|
*/
|
public void sendNotFound(HttpExchange e, String fname) throws IOException {
|
antwortSenden(e, SC_NOT_FOUND, fname + STR_NOT_FOUND);
|
}
|
|
public void antwortSenden(HttpExchange exchange, int code, String antwort) throws IOException {
|
byte[] bytes = antwort.getBytes();
|
exchange.sendResponseHeaders(code, bytes.length);
|
OutputStream os = exchange.getResponseBody();
|
os.write(bytes);
|
finish(os);
|
}
|
|
|
|
}
|