/* * Copyright (C) 2015 SoftIndex LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.datakernel.http; import io.datakernel.annotation.Nullable; import io.datakernel.async.ForwardingResultCallback; import io.datakernel.async.ResultCallback; import io.datakernel.bytebuf.ByteBuf; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @SuppressWarnings("ThrowableInstanceNeverThrown, WeakerAccess") public abstract class StaticServlet implements AsyncServlet { public static final Charset DEFAULT_TXT_ENCODING = StandardCharsets.UTF_8; public static final String DEFAULT_INDEX_FILE_NAME = "index.html"; // response for get request asking for root public static final HttpException BAD_PATH_ERROR = HttpException.ofCode(400, "Bad path and query section"); public static final HttpException METHOD_NOT_ALLOWED = HttpException.ofCode(405, "Only GET is being allowed"); protected StaticServlet() { } protected ContentType getContentType(String path) { int pos = path.lastIndexOf("."); if (pos != -1) { path = path.substring(pos + 1); } MediaType mime = MediaTypes.getByExtension(path); if (mime == null) { mime = MediaTypes.OCTET_STREAM; } ContentType type; if (mime.isTextType()) { type = ContentType.of(mime, DEFAULT_TXT_ENCODING); } else { type = ContentType.of(mime); } return type; } protected abstract void doServeAsync(String name, ResultCallback<ByteBuf> callback); protected HttpResponse createHttpResponse(ByteBuf buf, String path) { return HttpResponse.ofCode(200) .withBody(buf) .withContentType(getContentType(path)); } @Override public final void serve(final HttpRequest request, final ResultCallback<HttpResponse> callback) { String path = request.getRelativePath(); if (request.getMethod() != HttpMethod.GET) { callback.setException(METHOD_NOT_ALLOWED); return; } if (path.isEmpty() || path.charAt(0) != '/') { callback.setException(BAD_PATH_ERROR); return; } if (path.equals("/")) { path = DEFAULT_INDEX_FILE_NAME; } else { path = path.substring(1); // removing initial '/' } final String finalPath = path; doServeAsync(path, new ForwardingResultCallback<ByteBuf>(callback) { @Override protected void onResult(@Nullable ByteBuf buf) { callback.setResult(createHttpResponse(buf, finalPath)); } }); } }