I wrote a small program to download assets from GitHub releases:
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
public class GitTest
{
public static void main(String[] args) throws IOException
{
String assetUrlString = "https://api.github.com/repos/YuryMalyshev/SnakeGameWithProcessing/releases/assets/24010211";
String token = "Bearer My_Secret_GitHub_Personal_Access_Token";
String filename = "test.txt";
URL assetURL = new URL(assetUrlString);
HttpURLConnection downloadconnection = (HttpURLConnection) assetURL.openConnection();
downloadconnection.setConnectTimeout(0);
downloadconnection.addRequestProperty("Accept", "application/octet-stream");
downloadconnection.addRequestProperty("Authorization", token);
downloadconnection.connect();
// to partially mitigate the problem, we can put the problematic code
// into try-catch to get redirect URL
try
{
// throws IOException with message
//"Server returned HTTP response code: 400 for URL: ... if ran on Linux"
InputStream inStream = downloadconnection.getInputStream();
Files.copy(inStream, Paths.get(filename), StandardCopyOption.REPLACE_EXISTING);
}
catch(IOException e)
{
String responseMsg = e.getMessage();
if(responseMsg.contains("Server returned HTTP response code: 400 for URL"))
{
URL redirectURL = new URL(responseMsg.substring(responseMsg.indexOf("https://")));
HttpURLConnection redirectconnection = (HttpURLConnection)redirectURL.openConnection();
redirectconnection.connect();
InputStream inStream = redirectconnection.getInputStream();
Files.copy(inStream, Paths.get(filename), StandardCopyOption.REPLACE_EXISTING);
redirectconnection.disconnect();
}
}
downloadconnection.disconnect();
}
}
StackTrace:
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: https://github-production-release-asset-2e65be.s3.amazonaws.com/251348046/ca3bbd00-e0b0-11ea-8d30-49e495660664?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200817%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200817T145454Z&X-Amz-Expires=300&X-Amz-Signature=16f08a48455394dccdb94b91da32e4814885ae66c17d6f942ec814448b51975a&X-Amz-SignedHeaders=host&actor_id=49309415&repo_id=251348046&response-content-disposition=attachment%3B%20filename%3DTest.txt&response-content-type=application%2Foctet-stream
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1840)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at GitTest.main(GitTest.java:24)
Error Stream when getting Code 400
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>InvalidArgument</Code>
<Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message>
<ArgumentName>Authorization</ArgumentName>
<ArgumentValue>Bearer My_Secret_GitHub_Personal_Access_Token</ArgumentValue>
<RequestId>5C8A004BD481B671</RequestId>
<HostId>geSe0mXTd5ZFCskr7WK+9iI/RDx+mTTO/tgt25uGTK9v+fmUeM8qx6bkTSjPI3rgxPO4aNRrHEM=</HostId>
</Error>
It works fine on my Windows 10 machine, but when I try to execute it on Linux (RPi OS) the exception is thrown.
If I take the URL from the exception message and paste it into the browser (on Linux), then the file downloads just fine as well.
I tried to execute the program with sudo but the result is the same.
I guess one way would be to retrieve URL from the exception since I don't really know how it is generated, and use Runtime to execute cURL command. But I'd like to avoid it Just use redirect URL and continue with it.
Edit 1: cURL request would have the next form: curl -L -H "Accept: application/octet-stream" -H "Authorization: Bearer <token>" <url_to_the_asset> --output <name_of_the_file>
Edit 2: Added content of ErrorStream and partial solution