[SOLVED] Spring-boot and java UrlConnection

I have a small problem that I can’t figure out the answer for. I tried stackoverflow.com but as usual, at least for my questions there (0-5), crickets.

To summarize the problem, I have a download folder that is setup to permitAll() access and this works great.

The problem is that when the folder is empty and someone tries to get the file that should be there, rather than letting the exception happen or returning an error code, spring preempts the error and redirects to the login page, even when told to ignore resource errors. This in turn leads to a response code of 200 even though there was a problem.

I am not sure if this is a bug in spring due to the resource being outside the classpath, ie not inside the webapp or resources folder where static files usually reside or something extra I need to do to bypass the redirect.

If anyone is familiar enough with spring-boot and can help with the question, or maybe even direct me towards a different approach, Id appreciate it.

How is the resource being served?

I’ve only ever had static resources and things returned by REST calls.

I just use java UrlConnection to grab files, no controller.

Cant update the folder, if using a controller, without restarting server every time so I went with static folder using url.

For example.

http://localhost:port/resources/file_name

All that works as expected except if there is nothing in the folder, spring takes over and redirects to login instead of letting the error code be returned.

Edit: I shouldn’t say just if empty, any error will redirect to login.

Funny thing about stackoverflow, they have parasites that do nothing but make minor edits on every post so they can grab some tiny fraction of a point rather than answering questions.

Well, I mean the REST call could serve up whatever it wants, even files on the disk… but anyway, I’m still confused about something related to your setup.

I think we don’t really have enough information to help.

If it’s redirecting to a security layer then it means there is a security domain somehow in your container… and that security domain is setup to intercept the URL (or maybe the URL for the error page).

This is default behavior for spring-boot-starter. I have a custom Exception handler but it never gets the exception so I need to figure out how to bypass this part of the security just for this directory. Its must be tough or I smell bad or something as stack has no answer for it. They may of overlooked something or I may be doing something they didn’t account for.

I think I may have to go to the source to get an answer.

Yes but you have to reboot the server if you change the files. This setup uses file:/ as a resource so I can delete things or add without reboot.

Sorry @mitm I’m sure I have the answer for you but I’m not on my pc until tomorrow. I’m also home schooling my children because of this virus as well as work (I’m a self employed developer) so I’m slightly short of time right now. I will try my best to find time tomorrow.

I been at it two weeks so far and nothing works so I don’t mind at all.

No, I mean you REST call can load a “file:” object, too. And you don’t have to restart the server to pick it up. We do it in my day job all the time.

I’m not saying its the answer to your issue, but you can definitely do it:

@RequestParam(...etc...)
public String myRestCallThing() {
    return Files.toString(new File("/myDir/myCoolFile.txt"), Charsets.UTF_8);
}

Im going to try your way again. Ill get back shortly.

On the way to re-implementing the request, I stumbled across the culprit.

Nailed it.

I am hacking on a complete server setup to make my site. In it there is a LoginPageRedirectInterceptor that implements the HandlerInterceptorAdapter preHandle method,

I thought that since this was set,

    @Override
    public void configure(final WebSecurity web) {
        web.ignoring().antMatchers("/resources/**");
    }

it was not being called but it turns out it is for redirect errors, which should of been obvious to me really,

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response,
            Object handler) throws Exception {

        if (isInLoginPaths(this.urlPathHelper.getLookupPathForRequest(request)) && isAuthenticated()) {
            response.setContentType("text/html;charset=UTF-8");
            sendRedirect(request, response);
            return false;
        } else {
            log.info("[preHandle][" + request + "]" + "[" + request.getMethod()
                     + "]" + request.getRequestURI() + getParameters(request));

            return true;
        }
    }

preHandle is returning true to further process the url. If I set a false for the url, it will stop the redirect but still return and response code of 200.

Not sure how to safely end the redirect since this looks like it could lead to abuse if not done properly. I will go back and re implement the rest controller again and see if I can just do it that way since you say it should work and thats they way I wanted to do it from the start.

I will get back again with more info.

1 Like

Finally got this thing down. I was going about this completely wrong as @pspeed pointed out. The controller way works excellent when setup correctly.

My original setup for the controller was flawed because I believe that static resources, under the default resources or webapp folders, only get read during startup. Thats why they wouldn’t update when changed.

My new controller uses the file system and loads from the application root folder,

final Resource resource = resourceLoader.getResource("file:updater/" + restOfUrl);

where rest of url is the path to the file, including filename. This allows my custom exception to be thrown, which allows the updater to know there was a problem.

Using the addResourceHandlers directly via an url

http://localhost:port/resources/file_name

only works if everything goes smoothly. Removed that so now you have to go through the controller. Much safer also.

I am building this as resumable download. I have the client part setup properly but am not sure if the controller is setup correctly for it. I think its close though. I will start a new thread on that part in a few days, once I finish the updater code, assuming I haven’t deleted my hard drive by then.

Thanks for the help.

1 Like

I think a lot of containers will cache the files in their own virtual file system. So that sounds about right for web service class resources.

Edit: but any file on disk is fine as should be other resources in the container’s classpath that is not part of your “web app”.