Correctly calculate base url in the case a proxy server is present
Signed-off-by: Andrew DeMaria <lostonamountain@gmail.com>
This commit is contained in:
@@ -49,6 +49,23 @@ libresonic.war, you do not need to change anything.
|
|||||||
|
|
||||||
## Reverse proxy configuration
|
## Reverse proxy configuration
|
||||||
|
|
||||||
|
#### How it works
|
||||||
|
Libresonic expects proxies to provide information about their incoming URL so that Libresonic can craft it when needed.
|
||||||
|
To do so, Libresonic looks for the following HTTP headers:
|
||||||
|
|
||||||
|
- `X-Forwarded-Host`
|
||||||
|
- Provides server name and optionally port in the case that the proxy is on a non-standard port
|
||||||
|
- `X-Forwarded-Proto`
|
||||||
|
- Tells Libresonic whether to craft an HTTP or HTTPS url
|
||||||
|
- `X-Forwarded-Server`
|
||||||
|
- This is only a fallback in the case that `X-Forwarded-Host` is not available
|
||||||
|
|
||||||
|
Currently this is used wherever, `NetworkService#getBaseUrl` is called. A couple notable places include:
|
||||||
|
|
||||||
|
- Stream urls
|
||||||
|
- Share urls
|
||||||
|
- Coverart urls
|
||||||
|
|
||||||
### Nginx
|
### Nginx
|
||||||
|
|
||||||
The following configuration works for Nginx (HTTPS with HTTP redirection):
|
The following configuration works for Nginx (HTTPS with HTTP redirection):
|
||||||
@@ -74,6 +91,7 @@ server {
|
|||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
|
proxy_set_header X-Forwarded-Host $http_host;
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_max_temp_file_size 0;
|
proxy_max_temp_file_size 0;
|
||||||
proxy_pass http://127.0.0.1:4040;
|
proxy_pass http://127.0.0.1:4040;
|
||||||
@@ -98,6 +116,8 @@ The following configuration works for Apache (without HTTPS):
|
|||||||
|
|
||||||
### HAProxy
|
### HAProxy
|
||||||
|
|
||||||
|
**OUTDATED since `X-Forwarded-Host`/`X-FORWARDED-PROTO` change**
|
||||||
|
|
||||||
The following configuration works for HAProxy (HTTP and HTTPS):
|
The following configuration works for HAProxy (HTTP and HTTPS):
|
||||||
|
|
||||||
```haproxy
|
```haproxy
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.libresonic.player.service;
|
package org.libresonic.player.service;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.libresonic.player.Logger;
|
||||||
import org.springframework.web.util.UrlPathHelper;
|
import org.springframework.web.util.UrlPathHelper;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@@ -28,22 +30,62 @@ import java.net.URI;
|
|||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
|
||||||
public class NetworkService {
|
public class NetworkService {
|
||||||
|
|
||||||
|
private static UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||||
|
private static final String X_FORWARDED_SERVER = "X-Forwarded-Server";
|
||||||
|
private static final String X_FORWARDED_PROTO = "X-Forwarded-Proto";
|
||||||
|
private static final String X_FORWARDED_HOST = "X-Forwarded-Host";
|
||||||
|
|
||||||
|
private final static Logger LOG = Logger.getLogger(NetworkService.class);
|
||||||
|
|
||||||
public static String getBaseUrl(HttpServletRequest request) {
|
public static String getBaseUrl(HttpServletRequest request) {
|
||||||
try {
|
try {
|
||||||
UrlPathHelper urlPathHelper = new UrlPathHelper();
|
URI uri;
|
||||||
URL url = new URL(request.getRequestURL().toString());
|
try {
|
||||||
String host = url.getHost();
|
uri = calculateProxyUri(request);
|
||||||
String userInfo = url.getUserInfo();
|
} catch (Exception e) {
|
||||||
String scheme = url.getProtocol();
|
LOG.debug("Could not calculate proxy uri", e);
|
||||||
int port = url.getPort();
|
uri = calculateNonProxyUri(request);
|
||||||
|
}
|
||||||
|
|
||||||
URI uri = new URI(scheme, userInfo, host, port, urlPathHelper.getContextPath(request), null, null);
|
String baseUrl = uri.toString() + "/";
|
||||||
return uri.toString() + "/";
|
LOG.debug("Calculated base url to " + baseUrl);
|
||||||
|
return baseUrl;
|
||||||
} catch (MalformedURLException | URISyntaxException e) {
|
} catch (MalformedURLException | URISyntaxException e) {
|
||||||
throw new RuntimeException("Could not calculate base url", e);
|
throw new RuntimeException("Could not calculate base url", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static URI calculateProxyUri(HttpServletRequest request) throws URISyntaxException {
|
||||||
|
String xForardedHost = request.getHeader(X_FORWARDED_HOST);
|
||||||
|
if(!isValidXForwardedHost(xForardedHost)) {
|
||||||
|
xForardedHost = request.getHeader(X_FORWARDED_SERVER);
|
||||||
|
if(!isValidXForwardedHost(xForardedHost)) {
|
||||||
|
throw new RuntimeException("Cannot calculate proxy uri without HTTP header " + X_FORWARDED_HOST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
URI proxyHost = new URI("ignored://" + xForardedHost);
|
||||||
|
String host = proxyHost.getHost();
|
||||||
|
int port = proxyHost.getPort();
|
||||||
|
String scheme = request.getHeader(X_FORWARDED_PROTO);
|
||||||
|
|
||||||
|
return new URI(scheme, null, host, port, urlPathHelper.getContextPath(request), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isValidXForwardedHost(String xForardedHost) {
|
||||||
|
return StringUtils.isNotBlank(xForardedHost) && !StringUtils.equals("null", xForardedHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static URI calculateNonProxyUri(HttpServletRequest request) throws MalformedURLException, URISyntaxException {
|
||||||
|
URL url = new URL(request.getRequestURL().toString());
|
||||||
|
String host = url.getHost();
|
||||||
|
String scheme = url.getProtocol();
|
||||||
|
int port = url.getPort();
|
||||||
|
String userInfo = url.getUserInfo();
|
||||||
|
return new URI(scheme, userInfo, host, port, urlPathHelper.getContextPath(request), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user