001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.terminal.region; 018 019import java.io.*; 020import java.util.*; 021 022import org.apache.juneau.http.*; 023import org.apache.juneau.rest.server.*; 024 025/** 026 * Mixin interface that serves the terminal bytes and raw endpoints, plus this module's own JS and CSS. 027 * 028 * <p> 029 * The one abstract method is the application's resolver, which is where authorization lives: an unknown id and a 030 * forbidden id both answer {@code 404}. Ids match {@code ^[A-Za-z0-9_-]{1,128}$}; anything else answers {@code 400} 031 * before the resolver runs. The mixin adds no auth of its own; the host resource's guards apply. 032 * 033 * <p> 034 * Step events are not served here: pair the terminal with {@code TerminalViewMixin} over the same id. 035 * 036 * <h5 class='section'>Example:</h5> 037 * <p class='bjava'> 038 * <ja>@Rest</ja> 039 * <jk>public class</jk> RunsResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> TerminalMixin, TerminalViewMixin { 040 * <ja>@Override</ja> 041 * <jk>public</jk> Optional<TerminalSource> terminalSource(String <jv>id</jv>, RestRequest <jv>req</jv>) { 042 * <jk>return</jk> <jf>runs</jf>.find(<jv>id</jv>).map(Run::terminal); 043 * } 044 * } 045 * </p> 046 */ 047public interface TerminalMixin { 048 049 /** The URL path prefix of the terminal endpoints (relative to the host mount). */ 050 String TERMINAL_PREFIX = "/juneau-terminal"; 051 052 /** The URL path template of the bytes endpoint. */ 053 String BYTES_PATH = TERMINAL_PREFIX + "/{id}/bytes"; 054 055 /** The URL path template of the raw download. */ 056 String RAW_PATH = TERMINAL_PREFIX + "/{id}/raw"; 057 058 /** The URL path of the terminal runtime. */ 059 String JS_PATH = "/juneau-terminal.js"; 060 061 /** The URL path of the terminal stylesheet. */ 062 String CSS_PATH = "/juneau-terminal.css"; 063 064 /** The {@code WebJarResolver} asset id of the xterm.js UMD bundle. */ 065 String XTERM_JS_ASSET = "org.webjars.npm:xterm__xterm:xterm__xterm/{version}/lib/xterm.js"; 066 067 /** The {@code WebJarResolver} asset id of the xterm.js stylesheet. */ 068 String XTERM_CSS_ASSET = "org.webjars.npm:xterm__xterm:xterm__xterm/{version}/css/xterm.css"; 069 070 /** 071 * Resolves the source for a terminal id, applying the application's own access rules. 072 * 073 * @param id The id from the URL path (already checked against the grammar). 074 * @param req The in-flight request. 075 * @return The source, or empty when the id is unknown or the caller may not read it. 076 */ 077 Optional<TerminalSource> terminalSource(String id, RestRequest req); 078 079 /** 080 * [GET /juneau-terminal/{id}/bytes] — raw bytes from an offset. 081 * 082 * @param id The terminal id. 083 * @param req The request. 084 * @param res The response. 085 * @throws IOException If the response could not be written. 086 */ 087 @RestGet(path=BYTES_PATH, summary="Terminal bytes", swagger=@OpSwagger(ignore=true)) 088 default void terminalBytes(@Path("id") String id, RestRequest req, RestResponse res) throws IOException { 089 TerminalEndpoints.bytes(terminalSource(TerminalEndpoints.checkId(id), req), req, res); 090 } 091 092 /** 093 * [GET /juneau-terminal/{id}/raw] — the whole log as an attachment. 094 * 095 * @param id The terminal id. 096 * @param req The request. 097 * @param res The response. 098 * @throws IOException If the response could not be written. 099 */ 100 @RestGet(path=RAW_PATH, summary="Terminal raw log", swagger=@OpSwagger(ignore=true)) 101 default void terminalRaw(@Path("id") String id, RestRequest req, RestResponse res) throws IOException { 102 TerminalEndpoints.raw(terminalSource(TerminalEndpoints.checkId(id), req), id, res); 103 } 104 105 /** 106 * [GET /juneau-terminal.js] — the terminal runtime. 107 * 108 * @return The script. 109 */ 110 @RestGet(path=JS_PATH, summary="Juneau terminal runtime", swagger=@OpSwagger(ignore=true)) 111 default HttpResource terminalScript() { 112 return TerminalEndpoints.script(); 113 } 114 115 /** 116 * [GET /juneau-terminal.css] — the terminal stylesheet. 117 * 118 * @return The stylesheet. 119 */ 120 @RestGet(path=CSS_PATH, summary="Juneau terminal stylesheet", swagger=@OpSwagger(ignore=true)) 121 default HttpResource terminalStylesheet() { 122 return TerminalEndpoints.stylesheet(); 123 } 124 125 /** 126 * The absolute URL of a terminal asset; the toolkit pack resolver for the {@code terminal} pack. 127 * 128 * @param req The current request. 129 * @param path {@link #JS_PATH} or {@link #CSS_PATH}. 130 * @return The asset URL with its cache-buster. 131 */ 132 static String terminalAssetUrl(RestRequest req, String path) { 133 return TerminalEndpoints.terminalAssetUrl(req, path); 134 } 135}