content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.http.netty;
  
  import java.nio.charset.Charset;
  import java.util.stream.Collectors;
  import java.util.stream.StreamSupport;
  
  import io.netty.handler.codec.http.FullHttpRequest;
  import io.quarkus.runtime.annotations.RegisterForReflection;
  import jakarta.inject.Named;
  import org.apache.camel.Exchange;
  import org.apache.camel.builder.RouteBuilder;
  import org.apache.camel.component.netty.http.JAASSecurityAuthenticator;
  import org.apache.camel.component.netty.http.NettyHttpComponent;
  import org.apache.camel.component.netty.http.NettyHttpConfiguration;
  import org.apache.camel.component.netty.http.NettyHttpMessage;
  import org.apache.camel.component.netty.http.NettyHttpSecurityConfiguration;
  import org.apache.camel.component.netty.http.SecurityConstraintMapping;
  import org.apache.camel.component.rest.RestConstants;
  import org.apache.camel.model.rest.RestBindingMode;
  import org.apache.camel.quarkus.component.http.netty.auth.TestAuthenticator;
  import org.apache.camel.quarkus.component.http.netty.pojo.UserPojo;
  import org.eclipse.microprofile.config.ConfigProvider;
  
  @RegisterForReflection(targets = IllegalStateException.class, serialization = true)
  public class NettyHttpRoutes extends RouteBuilder {
      @Named("jaasConfig")
      NettyHttpSecurityConfiguration jaasConfig() {
          final NettyHttpSecurityConfiguration config = new NettyHttpSecurityConfiguration();
          config.setRealm("Quarkus");
          JAASSecurityAuthenticator jaas = new JAASSecurityAuthenticator();
          jaas.setName("Quarkus");
          config.setSecurityAuthenticator(jaas);
          return config;
      }
  
      @Named("securityConfig")
      NettyHttpSecurityConfiguration securityConfiguration() {
          final NettyHttpSecurityConfiguration config = new NettyHttpSecurityConfiguration();
          config.setRealm("Quarkus");
          config.setSecurityAuthenticator(new TestAuthenticator());
          return config;
      }
  
      // Each ACL configuration is using a separate route/endpoint, so all of them are using /* mapping
      @Named("acladmin")
      NettyHttpSecurityConfiguration aclAdmin() {
          final NettyHttpSecurityConfiguration config = securityConfiguration();
          SecurityConstraintMapping securityConstraintMapping = new SecurityConstraintMapping();
          securityConstraintMapping.addInclusion("/*", "admin");
          config.setSecurityConstraint(securityConstraintMapping);
          return config;
      }
  
      @Named("aclguest")
      NettyHttpSecurityConfiguration aclGuest() {
          final NettyHttpSecurityConfiguration config = securityConfiguration();
          SecurityConstraintMapping securityConstraintMapping = new SecurityConstraintMapping();
          securityConstraintMapping.addInclusion("/*", "admin,guest");
          config.setSecurityConstraint(securityConstraintMapping);
          return config;
      }
  
      @Named("aclpublic")
      NettyHttpSecurityConfiguration aclPublic() {
          final NettyHttpSecurityConfiguration config = securityConfiguration();
          SecurityConstraintMapping securityConstraintMapping = new SecurityConstraintMapping();
          securityConstraintMapping.addExclusion("/*");
          config.setSecurityConstraint(securityConstraintMapping);
          return config;
      }
  
      @Named("aclwildcard")
      NettyHttpSecurityConfiguration aclWildcard() {
          final NettyHttpSecurityConfiguration config = securityConfiguration();
          SecurityConstraintMapping securityConstraintMapping = new SecurityConstraintMapping();
          securityConstraintMapping.addInclusion("/*", "*");
          config.setSecurityConstraint(securityConstraintMapping);
          return config;
      }
  
      @Named("netty-http")
      NettyHttpComponent component() {
          NettyHttpComponent component = new NettyHttpComponent();
          NettyHttpConfiguration config = new NettyHttpConfiguration();
          // This helps to stabilize the tests when running on windows, as occasionally when invoking the same route from a parameterized test,
          // the next request got the same channel as the previous request that was not fully done yet and it caused the next test to fail.
          config.setReuseChannel(true);
          component.setConfiguration(config);
          return component;
      }
  
      @Override
      public void configure() throws Exception {
          from("direct:netty-http-https")
                  .to("netty-http:https://localhost:{{quarkus.http.test-ssl-port}}/service/common/https?ssl=true&sslContextParameters=#sslContextParameters");
          from("netty-http:http://0.0.0.0:{{camel.netty-http.test-port}}/test/server/hello")
                  .transform().constant("Netty Hello World");
          from("netty-http:http://0.0.0.0:{{camel.netty-http.test-port}}/test/server/serialized/exception?transferException=true")
                  .throwException(new IllegalStateException("Forced exception"));
          from("netty-http:http://0.0.0.0:{{camel.netty-http.compression-test-port}}/compressed?compression=true")
                  .transform().constant("Netty Hello World Compressed");
  
          restConfiguration().component("netty-http")
                  .host("localhost").port(ConfigProvider.getConfig().getValue("camel.netty-http.restPort", Integer.class));
  
          from("netty-http:http://localhost:{{camel.netty-http.port}}/request")
                  .process(ex -> {
                      final FullHttpRequest req = ex.getIn(NettyHttpMessage.class).getHttpRequest();
                      ex.getIn().setBody(
                              String.join(",", req.method().name(), req.content().toString(Charset.defaultCharset()),
                                      StreamSupport.stream(req.headers().spliterator(), false)
                                              .map(h -> h.getKey() + ":" + h.getValue()).collect(Collectors.joining(","))));
                  });
  
          from("netty-http:http://localhost:{{camel.netty-http.port}}/response").transform().simple("Received message ${body}");
  
          from("netty-http:http://localhost:{{camel.netty-http.port}}/auth?securityConfiguration=#securityConfig").log("success");
  
          from("netty-http:http://localhost:{{camel.netty-http.port}}/jaas?securityConfiguration=#jaasConfig").log("success");
  
          from("netty-http:http://localhost:{{camel.netty-http.port}}/acls/admin?securityConfiguration=#acladmin").log("success");
          from("netty-http:http://localhost:{{camel.netty-http.port}}/acls/guest?securityConfiguration=#aclguest").log("success");
          from("netty-http:http://localhost:{{camel.netty-http.port}}/acls/wildcard?securityConfiguration=#aclwildcard")
                  .log("success");
          from("netty-http:http://localhost:{{camel.netty-http.port}}/acls/public?securityConfiguration=#aclpublic")
                  .log("success");
  
          from("netty-http:http://localhost:{{camel.netty-http.port}}/wildcard?matchOnUriPrefix=true").setBody()
                  .constant("wildcard matched");
  
          from("netty-http:proxy://localhost:{{camel.netty-http.proxyPort}}?reuseChannel=false")
                  .toD("netty-http:http://${headers." + Exchange.HTTP_HOST + "}:${headers." + Exchange.HTTP_PORT + "}/${headers."
                          + Exchange.HTTP_PATH + "}");
          from("netty-http:http://localhost:{{camel.netty-http.port}}/proxy").setBody().constant("proxy");
  
          rest("/rest")
                  .get("/").to("seda:printMethod")
                  .post("/").to("seda:printMethod")
                  .put("/").to("seda:printMethod")
                  .post("/json").bindingMode(RestBindingMode.json).consumes("application/json").type(UserPojo.class)
                  .to("seda:printBody")
                  .post("/xml").bindingMode(RestBindingMode.xml).consumes("application/xml").type(UserPojo.class)
                  .to("seda:printBody");
  
          from("seda:printMethod").setBody().header(RestConstants.HTTP_METHOD);
          from("seda:printBody").process(e -> {
              e.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
              e.getIn().setBody(e.getIn().getBody(UserPojo.class).toString());
          });
      }
  }
  