【问题标题】:Issues using Retrofit2 to call GitHub REST API to update existing file使用 Retrofit2 调用 GitHub REST API 来更新现有文件的问题
【发布时间】:2021-07-24 08:34:06
【问题描述】:

我正在尝试使用 Retrofit 来调用 GitHub API to update the contents of an existing file,但在我的回复中收到 404。对于这个问题,我有兴趣更新this file。这是我为尝试实现这一目标而编写的主要代码: GitHubUpdateFileRequest

public class GitHubUpdateFileRequest {
  public String message = "Some commit message";
  public String content = "Hello World!!";
  public String sha = "shaRetrievedFromSuccessfulGETOperation";
  public final Committer committer = new Committer();

  private class Committer {
    Author author = new Author();
    private class Author {
      final String name = "blakewilliams1";
      final String email = "blake@blakewilliams.org";
    }
  }
}

**GitHubUpdateFileResponse **

public class GitHubUpdateFileResponse {
  public GitHubUpdateFileResponse() {}
}

GitHubClient

public interface GitHubClient {
  // Docs: https://docs.github.com/en/rest/reference/repos#get-repository-content
  // WORKS FINE
  @GET("/repos/blakewilliams1/blakewilliams1.github.io/contents/qr_config.json")
  Call<GitHubFile> getConfigFile();

  // https://docs.github.com/en/rest/reference/repos#create-or-update-file-contents
  // DOES NOT WORK
  @PUT("/repos/blakewilliams1/blakewilliams1.github.io/contents/qr_config.json")
  Call<GitHubUpdateFileResponse> updateConfigFile(@Body GitHubUpdateFileRequest request);
}

主逻辑

// Set up the Retrofit client and add an authorization interceptor
UserAuthInterceptor interceptor =
    new UserAuthInterceptor("blake@blakewilliams.org", "myActualGitHubPassword");
OkHttpClient.Builder httpClient =
    new OkHttpClient.Builder().addInterceptor(interceptor);

Retrofit.Builder builder =
    new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create());

Retrofit retrofit = builder.client(httpClient.build()).build();

client = retrofit.create(GitHubClient.class);

// Now make the request and process the response
GitHubUpdateFileRequest request = new GitHubUpdateFileRequest();
client.updateConfigFile(request).enqueue(new Callback<GitHubUpdateFileResponse>() {
  @Override
  public void onResponse(Call<GitHubUpdateFileResponse> call, Response<GitHubUpdateFileResponse> response) {
    int responseCode = response.code();
    // More code on successful update
  }

  @Override
  public void onFailure(Call<GitHubUpdateFileResponse> call, Throwable t) {
    Log.e("MainActivity", "Unable to update file" + t.getLocalizedMessage());
  }
});

目前发生的情况:
目前,成功回调被触发,但响应代码为 404,如下所示:

响应{protocol=http/1.1, code=404, message=Not Found, url=https://api.github.com/repos/blakewilliams1/blakewilliams1.github.io/contents/qr_config.json}

有没有其他人遇到过这种情况?我首先认为在 URL 中包含 '/content/' 是个问题,但我在读取文件内容请求时做同样的事情并且它工作正常(也使用相同的 URL 只是一个 GET 而不是 PUT)。

【问题讨论】:

    标签: java android rest retrofit2 github-api


    【解决方案1】:

    对于将来有兴趣这样做的人,我想出了解决方案。

    1. 我需要修改请求对象结构
    2. 我没有使用身份验证拦截器,而是在标头中添加了访问令牌。 Here is where you can create access tokens for Github,您只需要授予它“repos”选项的权限,这个用例就可以工作。

    这是我更新后的请求对象的样子:

    public class GitHubUpdateFileRequest {
      public String message;
      public String content;
      public String sha;
      public final Committer committer = new Committer();
    
      public GitHubUpdateFileRequest(String unencodedContent, String message, String sha) {
      this.message = message;
      this.content = Base64.getEncoder().encodeToString(unencodedContent.getBytes());
      this.sha = sha;
      }
    
      private static class Committer {
        final String name = "yourGithubUsername";
        final String email = "email@yourEmailAddressForTheUsername.com";
      }
    }  
    

    那么从我的代码中,我只想说:

    GitHubUpdateFileRequest updateRequest = new GitHubUpdateFileRequest("Hello World File Contents", "This is the title of the commit", shaOfExistingFile);
    

    为了使用这个请求,我更新了 Retrofit 客户端实现,如下所示:

    // https://docs.github.com/en/rest/reference/repos#create-or-update-file-contents
    @Headers({"Content-Type: application/vnd.github.v3+json"})
    @PUT("/repos/yourUserName/yourRepository/subfolder/path/to/specific/file/theFile.txt")
    Call<GitHubUpdateFileResponse> updateConfigFile(
        @Header("Authorization") String authorization, @Body GitHubUpdateFileRequest request);
    

    我这样称呼那个接口:

    githubClient.updateConfigFile("token yourGeneratedGithubToken", request);
    

    是的,您确实需要前缀“token”。您可以将该标头硬编码到界面中,但我将其传入,以便出于安全原因将其存储在版本控制范围之外的位置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      • 2018-05-01
      相关资源
      最近更新 更多