Search code examples
javagoogle-app-enginescribe

Strava V3 API Upload Using Scribe (on Google App Engine)


I am trying to use Scribe to upload a GPX file (not gzipped) to Strava using their V3 API (with Java, in Google App Engine):

String url = "https://www.strava.com/api/v3/uploads?access_token=<TOKEN>";
OAuthRequest req = new OAuthRequest(Verb.POST, url);
req.addQuerystringParameter("private", "1");
req.addQuerystringParameter("activity_type", "bike");
req.addQuerystringParameter("data_type", "gpx");
req.addQuerystringParameter("external_id", <Unique String>);

req.addHeader("Content-Type", "multipart/form-data");
String gpx = <Content of GPX file to Upload>;

req.addBodyParameter("file", gpx);

Response response = request.send();

Result is that I get a response code 500 (Internal Error) from Strava, and it doesn't upload the GPX activity.

I guess this is a problem to do with how I am forming the HTTP multipart POST, which is defined in the Strava documentation here as:

DEFINITION
POST https://www.strava.com/api/v3/uploads
EXAMPLE REQUEST
$ curl -X POST https://www.strava.com/api/v3/uploads \
-F access_token=83ebeabdec09f6670863766f792ead24d61fe3f9 \
-F activity_type=ride \
-F [email protected] \
-F data_type=fit


Parameters:
<OTHERS>
file: multipart/form-data required 
the actual activity data, if gzipped the data_type must end with .gz

Any ideas about how I can make this work please? Thank you.

EDIT: Discovered several things with my own further investigations:

  • Scribe is very much just about signing oauth, so the author is not focusing on adding functionality to handle multipart/form-data (although people have suggested such additions)
  • I could use one of the Apache classes (MultipartEntity) to do this, with Scribe, except that I think that Apache library is not supported under Google App Engine. See this thread, which would be perfect, except for the Apache / GAE problem

Solution

  • This is a complete solution. Pass your bearer token and filename to upload. This is for FIT files but would be a simple change for GPX. Taken from here:

    https://github.com/davidzof/strava-oauth/

    public static long uploadActivity(String bearer, String fileName) {
        JSONObject jsonObj = null;
    
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(
                "https://www.strava.com/api/v3/uploads");
        httpPost.addHeader("Authorization", "Bearer " + bearer);
        httpPost.setHeader("enctype", "multipart/form-data");
    
        MultipartEntity reqEntity = new MultipartEntity(
                HttpMultipartMode.BROWSER_COMPATIBLE);
        try {
            reqEntity.addPart("activity_type", new StringBody("ride"));
            reqEntity.addPart("data_type", new StringBody("fit"));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        FileBody bin = new FileBody(new File(fileName));
        reqEntity.addPart("file", bin);
    
        httpPost.setEntity(reqEntity);
    
        HttpResponse response;
        try {
            response = httpClient.execute(httpPost);
    
            HttpEntity respEntity = response.getEntity();
    
            if (respEntity != null) {
                // EntityUtils to get the response content
                String content = EntityUtils.toString(respEntity);
                System.out.println(content);
                JSONParser jsonParser = new JSONParser();
                jsonObj = (JSONObject) jsonParser.parse(content);
            }
        } catch (ParseException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    
        return (long) jsonObj.get("id");
    }