From 7e7c79e50fef71255a8bda135fddf7b1a515c37d Mon Sep 17 00:00:00 2001 From: Brad Wood Date: Mon, 22 Apr 2024 18:24:36 -0500 Subject: [PATCH] Add header and location compnents --- .../runtime/bifs/global/web/Location.java | 3 +- .../runtime/components/web/Header.java | 100 ++++++++++++++++++ .../runtime/components/web/Location.java | 75 +++++++++++++ 3 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 src/main/java/ortus/boxlang/runtime/components/web/Header.java create mode 100644 src/main/java/ortus/boxlang/runtime/components/web/Location.java diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/web/Location.java b/src/main/java/ortus/boxlang/runtime/bifs/global/web/Location.java index 1a6fb1a97..4100ca84b 100644 --- a/src/main/java/ortus/boxlang/runtime/bifs/global/web/Location.java +++ b/src/main/java/ortus/boxlang/runtime/bifs/global/web/Location.java @@ -39,7 +39,7 @@ public Location() { declaredArguments = new Argument[] { new Argument( true, "string", Key.URL, Set.of( Validator.NON_EMPTY ) ), new Argument( false, "boolean", Key.addToken ), - new Argument( false, "integer", Key.statusCode, 302, Set.of( Validator.min( 301 ), Validator.max( 399 ) ) ), + new Argument( false, "integer", Key.statusCode, 302, Set.of( Validator.min( 301 ), Validator.max( 399 ) ) ) }; } @@ -73,7 +73,6 @@ public Object _invoke( IBoxContext context, ArgumentsScope arguments ) { Integer statusCode = arguments.getAsInteger( Key.statusCode ); WebRequestBoxContext requestContext = context.getParentOfType( WebRequestBoxContext.class ); - HttpServerExchange exchange = requestContext.getExchange(); exchange.setStatusCode( statusCode ); diff --git a/src/main/java/ortus/boxlang/runtime/components/web/Header.java b/src/main/java/ortus/boxlang/runtime/components/web/Header.java new file mode 100644 index 000000000..08ce1fcf0 --- /dev/null +++ b/src/main/java/ortus/boxlang/runtime/components/web/Header.java @@ -0,0 +1,100 @@ +/** + * [BoxLang] + * + * Copyright [2024] [Ortus Solutions, Corp] + * + * 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 ortus.boxlang.runtime.components.web; + +import java.util.Set; + +import io.undertow.server.HttpServerExchange; +import io.undertow.util.HttpString; +import ortus.boxlang.runtime.components.Attribute; +import ortus.boxlang.runtime.components.BoxComponent; +import ortus.boxlang.runtime.components.Component; +import ortus.boxlang.runtime.context.IBoxContext; +import ortus.boxlang.runtime.scopes.Key; +import ortus.boxlang.runtime.types.IStruct; +import ortus.boxlang.runtime.types.exceptions.BoxValidationException; +import ortus.boxlang.runtime.validation.Validator; +import ortus.boxlang.web.WebRequestBoxContext; + +@BoxComponent +public class Header extends Component { + + public Header() { + super(); + declaredAttributes = new Attribute[] { + new Attribute( Key._NAME, "string", Set.of( + Validator.NON_EMPTY, + ( context, caller, record, records ) -> { + if ( !records.containsKey( Key.statusCode ) && !records.containsKey( Key._NAME ) ) { + throw new BoxValidationException( Key._NAME, record, "is required unless statusCode is provided." ); + } + } ) ), + new Attribute( Key.value, "string", "" ), + new Attribute( Key.charset, "String", "UTF-8" ), + new Attribute( Key.statusCode, "integer", Set.of( Validator.min( 100 ), Validator.max( 599 ) ) ), + new Attribute( Key.statusText, "string", "" ) + }; + } + + /** + * Generates custom HTTP response headers to return to the client. + * + * @param context The context in which the Component is being invoked + * @param attributes The attributes to the Component + * @param body The body of the Component + * @param executionState The execution state of the Component + * + * + * @atribute.name Header name + * + * @atribute.value HTTP header value + * + * @atribute.charset The character encoding in which to encode the header value. + * + * @atribute.statusCode The HTTP status code to return + * + * @atribute.statusText The HTTP status text to return + * + */ + public BodyResult _invoke( IBoxContext context, IStruct attributes, ComponentBody body, IStruct executionState ) { + String name = attributes.getAsString( Key._NAME ); + String value = attributes.getAsString( Key.value ); + // TODO: Figure out how to use charset, if at all. + String charset = attributes.getAsString( Key.charset ); + Integer statusCode = attributes.getAsInteger( Key.statusCode ); + String statusText = attributes.getAsString( Key.statusText ); + + WebRequestBoxContext requestContext = context.getParentOfType( WebRequestBoxContext.class ); + HttpServerExchange exchange = requestContext.getExchange(); + + if ( statusCode != null ) { + exchange.setStatusCode( statusCode ); + if ( statusText != null ) { + exchange.setReasonPhrase( statusText ); + } + } else { + // TODO: check and see if we remove existing headers, or just append + exchange.getResponseHeaders().add( + new HttpString( name ), + value + ); + } + + return DEFAULT_RETURN; + } +} diff --git a/src/main/java/ortus/boxlang/runtime/components/web/Location.java b/src/main/java/ortus/boxlang/runtime/components/web/Location.java new file mode 100644 index 000000000..dbc42146f --- /dev/null +++ b/src/main/java/ortus/boxlang/runtime/components/web/Location.java @@ -0,0 +1,75 @@ +/** + * [BoxLang] + * + * Copyright [2024] [Ortus Solutions, Corp] + * + * 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 ortus.boxlang.runtime.components.web; + +import java.util.Set; + +import io.undertow.server.HttpServerExchange; +import io.undertow.util.HttpString; +import ortus.boxlang.runtime.components.Attribute; +import ortus.boxlang.runtime.components.BoxComponent; +import ortus.boxlang.runtime.components.Component; +import ortus.boxlang.runtime.context.IBoxContext; +import ortus.boxlang.runtime.scopes.Key; +import ortus.boxlang.runtime.types.IStruct; +import ortus.boxlang.runtime.types.exceptions.AbortException; +import ortus.boxlang.runtime.validation.Validator; +import ortus.boxlang.web.WebRequestBoxContext; + +@BoxComponent +public class Location extends Component { + + public Location() { + super(); + declaredAttributes = new Attribute[] { + new Attribute( Key.URL, "string", Set.of( Validator.NON_EMPTY ) ), + new Attribute( Key.addToken, "boolean" ), + new Attribute( Key.statusCode, "integer", 302, Set.of( Validator.min( 301 ), Validator.max( 399 ) ) ) + }; + } + + /** + * Generates custom HTTP response headers to return to the client. + * + * @param context The context in which the Component is being invoked + * @param attributes The attributes to the Component + * @param body The body of the Component + * @param executionState The execution state of the Component + * + * + * @atribute.URL The URL of web page to open. + * + * @arguments.addToken clientManagement must be enabled. + * + * @argument.statusCode The HTTP status code. + * + */ + public BodyResult _invoke( IBoxContext context, IStruct attributes, ComponentBody body, IStruct executionState ) { + String URL = attributes.getAsString( Key.URL ); + Boolean addToken = attributes.getAsBoolean( Key.addToken ); + Integer statusCode = attributes.getAsInteger( Key.statusCode ); + + WebRequestBoxContext requestContext = context.getParentOfType( WebRequestBoxContext.class ); + HttpServerExchange exchange = requestContext.getExchange(); + + exchange.setStatusCode( statusCode ); + exchange.getResponseHeaders().put( new HttpString( "location" ), URL ); + + throw new AbortException(); + } +}