I need a jetty server with multiple servletHandler.
HTTPservlet:
ServletHandler servletHandler = new ServletHandler();
server.setHandler(servletHandler);
servletHandler.addServletWithMapping("com.realtime.webserver.MyServlet", "/MyServlet");
WebsocketServlet:
MyWebSocketHandler myWebSocketHandler = new MyWebSocketHandler ();
myWebSocketHandler.setHandler(new DefaultHandler());
server.setHandler(myWebSocketHandler);
server.start();
I need both should be in single server.
Is there any possibilities?
You can use org.eclipse.jetty.server.handler.HandlerCollection (Jetty 9)
HandlerCollection handlerCollection = new HandlerCollection();
handlerCollection.setHandlers(new Handler[] {servletHandler, myWebSocketHandler});
Later add handlers to the collection:
handlerCollection.addHandler(newHandler);
Finally,
server.setHandler(handlerCollection);
server.start();
http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyHandlers.java
This is an example of using many handlers at once on the same server.
Eventually it will be added to the documentation here:
http://www.eclipse.org/jetty/documentation/current/embedded-examples.html
Until that time there are many other examples there that should help make things clearer as well.
Related
I'm trying to protect my webapi with IdentityServer and OpenID Connect using Autofac. I'm using OWIN. But for some reason I can't get claims of the user. It seems that AccessTokenValidation is not triggered at all. That makes me think there is something wrong in the order of my declarations at my startup. Here is my startup.
public class Startup {
public void Configuration(IAppBuilder appBuilder) {
// Add authentication
this.AddAuthentication(appBuilder);
HttpConfiguration config = new HttpConfiguration();
var container = CreateAutofacContainer();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
WebApiConfig.Register(config);
config.EnsureInitialized();
// Register config - you can't add anything to pipeline after this
appBuilder.UseAutofacMiddleware(container);
appBuilder.UseAutofacWebApi(config);
appBuilder.UseWebApi(config);
}
private static IContainer CreateAutofacContainer() {
var autofacBuilder = new ContainerBuilder();
var assembly = Assembly.GetExecutingAssembly();
// Register your Web API controllers.
autofacBuilder.RegisterApiControllers(assembly);
// For general logging implementation
autofacBuilder.RegisterType<ConsoleLogger>().As<ILogger>();
// Create empty usage context to be filled in OWIN pipeline
IUsageContext usageContext = new RuntimeUsageContext();
autofacBuilder.RegisterInstance(usageContext).As<IUsageContext>().SingleInstance();
// We need to get usage context builded
autofacBuilder.RegisterType<OIDCUsageContextProvider>().InstancePerRequest();
var container = autofacBuilder.Build();
return container;
}
private void AddAuthentication(IAppBuilder app) {
var options = new IdentityServerBearerTokenAuthenticationOptions();
options.Authority = "MYAUTHORITY";
options.RequiredScopes = new[] { "openid", "profile", "email", "api" };
options.ValidationMode = ValidationMode.ValidationEndpoint;
app.UseIdentityServerBearerTokenAuthentication(options);
// Add local claims if needed
app.UseClaimsTransformation(incoming => {
// either add claims to incoming, or create new principal
var appPrincipal = new ClaimsPrincipal(incoming);
// incoming.Identities.First().AddClaim(new Claim("appSpecific", "some_value"));
return Task.FromResult(appPrincipal);
});
}
I'm using hybrid flow and api is called from SPA-application. I've verified (by calling my identity server's endpoint directly) that access token is valid and there are claims available. I also downloaded IdentityServer.AccessTokenValidation project and attached it as a reference. When I set some breakpoints to methods in that project, they never get called. That is why I think there is something wrong with my startup and OWIN pipeline.
I've declared UsageContext in my startup. It is a class I'm using to collect claims and some configuration settings - to be injected to actual controllers. I think it would be nice way to handle this, so in controllers there is always valid UsageContext available.
I've read a lot of samples and examples but still haven't found exactly same situation. I'll appreciate any attempts to point me into right direction.
Regards,
Borre
Could it be your registration of UsageContext as a Singleton? You mention this class contains claims, so this object should be resolved once pr http request - shouldn't it?
It turned out that there was some mysterious line in AccessTokenValidation - library that didn't work. I use that library to get claims. After changing the line everything seemed to work.
So basically my question is closed now and stuff works. But I'm still not totally convinced this is the right way to do this.
Thanks John for your comments!
I guess netty is best java networking framework ever i know, after reading and try some sample i have question:
1. What the best way to create Network Server for multi port with different protocol using netty 4.0?
Each server create :
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap(); // (2)
Each Server Running Inside Thread
is that right way?
2. Websocket Server
How to securing Websocket Server for Cross origin case? I don't have any reference about it
Your help very appreciate,
Regards
BC,
As Norman said, the important thing is that you need to share the event loop groups so that you do not create way too many threads. As long as you share the event loop groups, you can create as many ServerBootstraps as you wish:
EventLoopGroup bossGroup = new NioEventLoopGroup(numBossThreads);
EventLoopGroup workerGroup = new NioEventLoopGroup(numWorkerThreads);
ServerBootstrap sb1 = new ServerBootstrap();
sb1.group(bossGroup, workerGroup);
...
sb1.bind();
ServerBootstrap sb2 = new ServerBootstrap();
sb2.group(bossGroup, workerGroup);
...
sb2.bind();
ServerBootstrap sb3 = new ServerBootstrap();
sb3.group(bossGroup, workerGroup);
...
sb3.bind();
The bossGroup is used to accept the incoming connections, and the workerGroup is used to handle the connections accepted by the bossGroup. Please do some performance tests and specify the optimal numBossThreads and numWorkerThreads.
I would share the NioEventLoopGroup between the ServerBootstrap to share the same threads.
I am trying to understand how the self host configuration based Integration Tests are running.
In the code below, Should I be registering my config with the WebApiConfig. Registering or not seems to make no difference.
Is the full pipeline really being tested or is this an illusion? Since, If I am not using the config and the routes defined in my API instead declaring my own as I have done here, I am probably just not testing the full pipleine.
Is there any othere way of testing the api completely. The code below is testing a lot of things besides just my pipeline(like the client, SelfHosting etc..). This seems like an overkill to me. Any ideas ?
var config = new HttpSelfHostConfiguration("http://localhost:9090/");
config.Routes.MapHttpRoute("Default", "{api}/{controller}/{id}", new { id = RouteParameter.Optional });
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
MyApiProject.WebApiConfig.Register(config);
using (var server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
using (var client = new HttpClient())
{
using (var response = client.PostAsync("http://localhost:9090/api/login",
new FormUrlEncodedContent(new List<KeyValuePair<string,string>> { new KeyValuePair<string, strin("Foo","Bar)}), CancellationToken.None).Result)
{
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
using (var response = client.GetAsync("http://localhost:9090/api/login").Result)
{
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}
server.CloseAsync().Wait();
}
If you just want to test your controllers, you can write more targeted unit tests to test them. If you want to test the full pipeline your code looks fine except that instead of using a selfhost, you can just use HttpServer saving the network overhead. Also, if you are testing the full pipeline it is better to use the routes that you have in your actual app rather than adding a new route as that would be testing routing as well.
Also, refer to this blog post by Youssef for some ideas on testing your web APIs.
I'm working on using the .Net SDK to help automate the deployment of an application into Windows EC2 instances. The process I want to achieve is:
Create a new EC2 instance - this
"bootstraps" itself by loading in
the new application version using a
service.
Ensure the new instance is in the
'running' state
Run some simple acceptance tests on
the new instance.
Register the new instance with an
existing Elastic Load balancer that
has an instance running the old
version of the application.
When the new instance is registered
with the load balancer, de-register
the old instance.
Stop the old EC2 instance.
I've managed to get steps 1 and 2 working, and I'm pretty confident about 3 and 6.
To do this I've been writing a simple C# console app that uses the AWS .Net SDK v1.3.2 to make the various API calls.
However, when I get to step 4 I cannot get the new instance registered with the load balancer. Here is my code:
public IList<Instance> PointToNewInstance(string newInstanceId)
{
var allInstances = new List<Instance>();
using (var elbClient = ClientUtilities.GetElbClient())
{
try
{
var newInstances = new List<Instance> {new Instance(newInstanceId)};
var registInstancesRequest = new RegisterInstancesWithLoadBalancerRequest
{
LoadBalancerName = LoadBalancerName,
Instances = newInstances
};
var registerReponse = elbClient.RegisterInstancesWithLoadBalancer(registInstancesRequest);
allInstances = registerReponse.RegisterInstancesWithLoadBalancerResult.Instances;
var describeInstanceHealthRequest = new DescribeInstanceHealthRequest
{
Instances = newInstances
};
DescribeInstanceHealthResponse describeInstanceHealthResponse;
do
{
describeInstanceHealthResponse = elbClient.DescribeInstanceHealth(describeInstanceHealthRequest);
} while (describeInstanceHealthResponse.DescribeInstanceHealthResult.InstanceStates[0].State == "OutOfService");
_log.DebugFormat("New instance [{0}] now in service - about to stop remove old instance", newInstanceId);
if (allInstances.Any(i => i.InstanceId != newInstanceId))
{
elbClient.DeregisterInstancesFromLoadBalancer(new DeregisterInstancesFromLoadBalancerRequest
{
Instances = allInstances.Where(i => i.InstanceId != newInstanceId).ToList(),
LoadBalancerName = LoadBalancerName
});
foreach (var instance in allInstances.Where(i => i.InstanceId != newInstanceId).ToList())
{
_log.DebugFormat("Instance [{0}] has now been de-registered from load-balancer [{1}]", instance.InstanceId, LoadBalancerName);
}
}
}
catch (Exception exception)
{
_log.Error(exception);
}
}
return allInstances.Where(i => i.InstanceId != newInstanceId).ToList();
}
The code just freezes at this line:
var registerReponse = elbClient.RegisterInstancesWithLoadBalancer(registInstancesRequest);
When I looked in more detail at the documention (relevant documentation here) I noticed this line:
NOTE: In order for this call to be
successful, the client must have
created the LoadBalancer. The client
must provide the same account
credentials as those that were used to
create the LoadBalancer.
Is it actually possible to use the API to register new instances with an existing load balancer?
All of that is easy to implement. Use Auto Scaling. Use API.
As Roman mentions, it sounds like Auto Scaling is a good way for you to go, it may not solve all of your problems but its certainly a good starting point:
-an auto scaling group can be tied to a load balancer, e.g. ill have x healthy instances
-new instances are automatically added to the load balancer (no traffic will be sent until it passed the health check)
-you can define custom health checks, such as ping http://hostname/isalive just have your instance respond to these requests once its passes step 3
-you can define scaling policies but by default if you're over capacity the oldest instances will be killed
-you don't mention the use case of the app but if you don't want a public facing address you can use an internal load balancer that doesn't take any traffic, just looks after the health check
-where possible you should always use least privilege principles for security, with your method you're going to have to give every instance a lot of power to control other instances, whether through mistake or abuse this can go wrong very easily
I want to prevent my CSSs from being cached on the browser side. How can I do it in embedded Jetty instance?
If I were using xml configuration file, I would add lines like:
<init-param>
<param-name>cacheControl</param-name>
<param-value>max-age=0,public</param-value>
</init-param>
How I can turn that into the code?
Right now I start Jetty this way:
BasicConfigurator.configure();
Server server = new Server();
SocketConnector connector = new SocketConnector();
// Set some timeout options to make debugging easier.
// 1 hour
connector.setMaxIdleTime( 1000 * 60 * 60 );
connector.setSoLingerTime( -1 );
connector.setPort( 8081 );
server.setConnectors( new Connector[] { connector } );
WebAppContext bb = new WebAppContext();
bb.setServer( server );
bb.setContextPath( "/" );
bb.setWar( "src/webapp" );
server.addHandler( bb );
I think I should search setControlCache somewhere in the WebAppContext area of responsibility.
Any advices on this?
I normally use a ServletHolder, like this:
WebAppContext context = new WebAppContext();
ServletHolder servletHolder = new ServletHolder(MyServlet.class);
servletHolder.setInitParameter("cacheControl","max-age=0,public");
context.addServlet(servletHolder, "myservletpath");
While this does not exactly match your code you should be able to figure it out from there ?
Duh, how to do just the opposite How to configure cache for static resources in web.xml for Jetty??
And here's just a working code with no need to figure out, guess and try. It's provided with respect to code in question and jetty 6. For jetty 7 and higher need to change Context to ServletContextHandler.
BasicConfigurator.configure();
Server server = new Server();
SocketConnector connector = new SocketConnector();
// Set some timeout options to make debugging easier.
// 1 hour
connector.setMaxIdleTime( 1000 * 60 * 60 );
connector.setSoLingerTime( -1 );
connector.setPort( 8081 );
server.setConnectors( new Connector[] { connector } );
//--- The difference with code in question starts here
DefaultServlet defaultServlet = new DefaultServlet();
ServletHolder holder = new ServletHolder(defaultServlet);
holder.setInitParameter("useFileMappedBuffer", "false");
holder.setInitParameter("cacheControl", "max-age=0, public");
Context bb = new Context();
bb.setResourceBase("src/webapp");
bb.addServlet(holder, "/");
//--- Done. Caching is off!
server.addHandler( bb );
// Run server as usual with server.run();
My sample also sets useFileMappedBuffer to false which is needed for not blocking files on a disk if you are developing on Windows by any reason.
I use resourceHandler for static contents.
Here's a code working fine on Jetty 9.
ResourceHandler rh = new ResourceHandler();
rh.setResourceBase([your_resource_base_dir]);
rh.setCacheControl("no-store,no-cache,must-revalidate");