KTOR Server StatusPages status() not working - kotlin

I'm creating a website using KTOR v2.0.0 and I'm trying to set up StatusPages for the 404 & 500 error codes.
Locally this works as expected using the embedded server running the application through Intellij.
When I package the application to a WAR file and run it on a remote server the status() part doesn't seem to get triggered at all but the exception does.
install(StatusPages) {
println("StatusPages installed")
exception<Throwable> { call, cause ->
println("StatusPages exception triggered")
}
status(HttpStatusCode.NotFound) { call, status ->
println("Page not found!")
}
status(HttpStatusCode.Found) { call, status ->
println("Page WAS found!")
}
}
The exception works fine but neither of the status() calls work remotely, even though they work fine locally.
I'm using Jetty9 to call the WAR files and I'm using NGINX as a proxy from a domain name to the Jetty9 port. Is there something I'm missing in the process/setup for it to not work?
Any suggestions would be appreciated.

Related

How to restart Kestrel Hosted in Windows Service?

I want to restart Kestrel (asp.net core 3.1) via an authorized http request.
Kestrel is contained in a Windows service configured to restart itself automatically upon failure.
As far as i know the simplest way is to return an exit code different from 0, windows will do all the rest.
In light of that, the code I wrote is actually simple:
public MaintenanceController(IHostApplicationLifetime hostLifetime)
{
this.HostLifetime = hostLifetime ?? throw new ArgumentNullException(nameof(hostLifetime));
}
[HttpPost]
[Route("service/restart")]
[Authorize("AdminOnly")]
public ActionResult RestartService()
{
Program.IsRestart = true; //see below
this.HostLifetime.StopApplication();
//this does not work!
if (HostLifetime is WindowsServiceLifetime lifetime)
{
lifetime.ExitCode = 1;
}
//neither this!
Environment.ExitCode = 1;
return Ok();
}
The only way to make windows restarts the service is just actually call
Environment.Exit(1);
without HostLifetime.StopApplication();
But the issue with Environment.Exit called alone is it causes a non graceful shutdown, something I want absolutely to avoid.
Another approach I tried, to force an exit code different from 0, which did not work, was to put in Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLifetime)
{
[...]
applicationLifetime.ApplicationStopped.Register(() =>
{
//this can be set in the controller
if (Program.IsRestart)
{
Environment.Exit(1);
}
});
}
but, when called after ApplicationStopped, Environment.Exit(1) does apparently nothing, in fact even inside event viewer there is no trace of the services' shutdown with error, so windows does nothing.
UPDATE
Going back to classic, I changed the Main entry point to return an int and returned 1.
Still windows does not restart the service nor a failure entry is written to event viewer. It looks like is always stopped gracefully
Everything is working like it should. You may want to consider writing a wrapper batch file or watcher process.
Your watcher would wait for the process to exit, and if a flag file (e.g. .staydown) is present, it would exit gracefully. If the file doesn't exist, it would then restart the process.
In your RestartService method, use Environment.Exit(0) which would be a graceful shutdown, but since the .staydown file doesn't exist, your watcher would then restart the server. Your watcher would only stop running if the .staydown file exists and then the server is stopped, or the Windows Service itself is stopped.
When your app starts up, be sure to delete .staydown if present.
If you have node installed, you might be able to use a utility like forever in place of the watcher batch file.
You need to check the 'Enable actions for stops with errors' on the service, or run 'sc failureflag "My Service" 1'
More info here: https://blog.stephencleary.com/2020/06/servicebase-gotcha-recovery-actions.html
(this is a very strange behaviour on Windows part I think, honouring exit codes should be default!)

connection refused by server error when codenameone project is copied to another machine

I have a very strange problem:
I have created a project in Intellij using the Codename One plugin.
In this project I access a Google Sheet using Oauth2 authentication
following these directions from the Codename One site.
https://www.codenameone.com/google-login.html
My code to do this works fine on my computer (Windows 10).
If I copy that code to another computer (Windows 10 or OS X) and try to access the Google Sheet, I get a "Connection refused by server" error.
Specifically, I get the error after I click on the "Allow" button in
the Google Login dialog box.
I have tried this on several computers.
I receive the error no matter what network/ISP I am using when I try to access the Google Sheet.
The stack trace relating to the error looks like this:
java.lang.Throwable: Connection refused by server
at javafx.scene.web.WebEngine$LoadWorker.describeError(WebEngine.java:1461)
at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1400)
at javafx.scene.web.WebEngine$LoadWorker.access$1200(WebEngine.java:1278)
at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:1265)
at com.sun.webkit.WebPage.fireLoadEvent(WebPage.java:2443)
at com.sun.webkit.WebPage.fwkFireLoadEvent(WebPage.java:2287)
at com.sun.webkit.network.URLLoader.twkDidFail(Native Method)
at com.sun.webkit.network.URLLoader.notifyDidFail(URLLoader.java:883)
at com.sun.webkit.network.URLLoader.lambda$didFail$102(URLLoader.java:866)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Process finished with exit code 0
The code that is being executed when the error is generated is:
public void oauth2GoogleLogin()
{
String clientId = "xxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com";
String redirectURI = "http://localhost:8080";
String clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxx";
Login gc = GoogleConnect.getInstance();
gc.setClientId(clientId);
gc.setRedirectURI(redirectURI);
gc.setClientSecret(clientSecret);
gc.setScope("https://www.googleapis.com/auth/spreadsheets");
gc.setCallback(new LoginCallback() {
#Override
public void loginFailed(String errorMessage) {
super.loginFailed(errorMessage);
}
#Override
public void loginSuccessful() {
super.loginSuccessful();
System.out.println("Logged in.");
token = gc.getAccessToken().getToken();
//saveData();
}
});
if(!gc.isUserLoggedIn()){
gc.doLogin();
}else{
....some code to do stuff...
}
}
As I have said, this code works fine on the computer where I wrote it, but if I transfer the Intellij/Codename One project to another computer, it no longer works.
It seems to me that the problem is probably in the callback, and that the server that is refusing the connection is probably my own computer being accessed via the http://localhost:8080. But I'm not sure. Can anyone enlighten me?
If both machines no longer work that makes more sense that a regression in newer versions of JavaFX's web browser broke the Google OAuth2 process.
Unfortunately, that's a huge problem. We can't fix JavaFX and if they push out a broken update we are stuck.
A workaround might be to try an older version of the VM e.g. 1.8.67 or something.

RedirectPermanent working on local server but giving Error 500.19 on remote

We are trying to deploy a new ASP.NET Webapplication. To ensure compatibility with older clients who use a webservice at an URL which is not valid anymore I do the following workaround:
In the area registration:
context.MapRoute("Webservices_legacy_compatibility", "OldName/webservices/getVersion", new {controller = "Redirect", action = "Index"});
The RedirectController has this method:
public ActionResult Index(string name)
{
return RedirectPermanent("/Webservices/Update/GetLatestVersionLegacy?name=" + name);
}
Now on the local Visual Studio Development Server everything works as expected, but once I deploy to the remote IIS 7.5 I get a HTTP Error 500.19 - Internal Server Error telling me, that it can't find a web.config file in \path here\OldName\web.config
Note: Access to /Webservices/Update/GetLatestVersionLegacy directly is working on the remote!
I found the solution by contacting the server admin, there was another application pool assigned at OldName, once they got rid of it, the problem went away.

Java scribe does not generate signature on Tomcat

I am using scribe 1.3.0 for OATH authentication. This is on Tomcat 7 under Ubuntu.
I am pretty sure this is some sort of a pilot error but cannot figure out what is wrong exactly...
I create the service and token in the constructor of my client class:
public Client()
{
m_service = new ServiceBuilder()
.provider(Api.class)
.apiKey(CONSUMER_KEY)
.apiSecret(CONSUMER_SECRET)
.debug()
.build();
m_accessToken = new Token(OAUTH_TOKEN, OAUTH_TOKEN_SECRET);
}
Later on when time comes to make a request I use the service in a function:
OAuthRequest request = new OAuthRequest(Verb.GET,
url);
m_service.signRequest(m_accessToken, request);
Since I added the debug() tag to the ServiceBuilder I get the following output:
signing request: URL
setting token to: Token[xxxx , xxxxx]
generating signature...
thats it.. nothing else happens, the code just seems to die there.
I tried to catch Exception from the m_service call but it does not throw exception.
I had tried this code before on a different Windows machine with Jetty and it worked but I dont have access to that machine or OS anymore..
What could I be doing wrong? Is there anything else I can do to get more debug output?
-Wish
Turns out that I needed to include the apache codec jar files in Tomcat.
I did go back to try my app on Jetty again under Windows, that worked without the codec. I am not entirely sure why linux+Tomcat needs apache codec while Jetty+Windows7 does not..
If I had Maven would not have this issue..

WP7 error: "The remote server returned an error: NotFound."

I have this code that it used to work, but at some specific time it stopped to work and returned the error "The remote server returned an error: NotFound."
WebClient deliciousWebClient = new WebClient();
deliciousWebClient.Credentials = Credentials;
deliciousWebClient.DownloadStringAsync(new Uri("https://api.del.icio.us/v1/tags/get"));
deliciousWebClient.DownloadStringCompleted += (s, ee) =>
{
if (ee.Error == null)
{
…
Any suggestion on this error?
In this code, the error is pointing to delicious endpoit, but the same error is happening with some other services...
The NotFound error is a classic 404 error, so it's possible that the API endpoint is down or that it changed on you.
I'd start by using Fiddler2 to make the requests manually. That'll help you figure out whether the issue is in your code somewhere or on the API side.
It's hard to get Fiddler working with the WP7 emulator, as you noted below. One trick I've used in the past when I got really desperate was to write a quick console app that used the same code that my Windows Phone app was executing. Then I was able to successfully intercept the traffic. It turned out that my request being properly formatted.