Java
GitHub

JavaのSocketAPIからGitHubAPIを呼び出す part2

始めに

JavaのSocketAPIからGitHubのRestAPIを呼び出すの続きです
GitHubに対してファイルをリポジトリにコミットするGitHub APIをJavaのSoceketAPIから呼び出してみます

実装に関するメモ

1.Javaのロジックを実装する前にやること

GitHubのリポジトリに変更を加える処理を行うため、GitHubAPIを呼び出す際の認証を考える必要があります。
今回はOAuth2認証で認証を行うため、事前にGitHub上でPersonalアクセストークンを発行します
(Personalアクセストークンの発行の方法は後述の参考サイトに詳しい情報があります)

2.Javaのロジックについて

前回の実装から追加した点

前回の実装から、以下の処理を追加しています

  • GitHubに必要なパラメタを生成するためにjsonを生成するロジックを追加している
  • GitHubにコミットするファイルをBase64形式に変換するロジックを追加している

実行結果に関するメモ

  • 認証トークンが設定されていない場合は404エラーが返却される
  • 送信メソッドにPUT以外を指定すると404エラーが返却される
  • GitHubに送信するjsonパラメタに不備があると422エラーが返却される
  • 送信先のパスには必ずファイル含めることを指定すること
    ディレクトリを指定すると422エラーが返却される

参考サイト

  • GithubAPIについて色々とまとめてみた
    GitHubAPIに関する基本的な認証の関する記載があります。
    GitHubAPIを実装する際に一読するべきサイトです
  • Contents
    GitHubのリポジトリ情報を取得するRestAPIの仕様が記載されています

ソース

Test.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;


import com.fasterxml.jackson.databind.ObjectMapper;


public class Test {
    //GitHubのREST API v3を使ってGitHubのリポジトリにファイルを追加する
    //REST API v3の形式は
    // /repos/:owner/:repo/contents/:path
    //となる
    private static final String ACCESS_KEY ="*********";
    private static final String GITHUB_RESTAPI_PATH = "https://api.github.com/repos/triple4649/images/contents/img/mypicture.png?access_token=%s";
    public static void main(String[] args) throws Exception {

        HttpsURLConnection con = createHttpsURLConnection(String.format(GITHUB_RESTAPI_PATH, ACCESS_KEY)
                ,"PUT");

        //RestAPIでイメージファイルをGitHubにコミットする
        putContents(con,createJson());
        //RestAPIのレスポンスのヘッダー情報を出力する
        printHeaderFields(con);
        //RestAPIのレスポンスの結果を出力する
        printBody(con);
        con.disconnect();
    }

    //StreamにJSONを書きだす
    private static void putContents(HttpsURLConnection con,byte[] b) throws Exception{
        con.setDoOutput(true);
        OutputStream o = con.getOutputStream();
        o.write(b);
        o.flush();
    }

    //指定したパスのファイルをBase64形式に変換する
    public static String converToBase64(String path)throws Exception{
        return Base64.getEncoder()
                .encodeToString(
                        Files.readAllBytes(Paths.get(path)));
    }

    //HTTPの送信メソッドを指定してHttpsURLConnectionを生成する
    private static HttpsURLConnection  createHttpsURLConnection (String path,String method) throws Exception{
        HttpsURLConnection con = createHttpsURLConnection (path);
        con.setRequestMethod(method);
        return con;
    }


    //GitHubにコミットするデータを生成する
    private static byte[] createJson() throws Exception{
        Map <String,Object> map = new LinkedHashMap<String,Object>();
        Map <String,String> nestmap=new LinkedHashMap<String,String>();
        nestmap.put("name", "triple");
        nestmap.put("email", "triple_55@yahoo.co.jp");
        map.put("committer",nestmap);
        map.put("message","GitHub API");
        map.put("content",converToBase64("./CA390046.JPG"));
        return new ObjectMapper()
        .writeValueAsBytes(map);
    }


    //TLS接続用のURLConnectionを生成する(認証の検証なし版)
    //リクエストメソッドはデフォルト(Get)
    private static HttpsURLConnection  createHttpsURLConnection (String path) throws Exception{
        SSLSocketFactory factory = null;
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, new NonAuthentication[] { new NonAuthentication() },
                null);
        factory = ctx.getSocketFactory();

        URL url = new URL(path);
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setSSLSocketFactory(factory);
        return con;
    }

    //header情報を出力する
    private static void printHeaderFields(HttpsURLConnection con){
        con.getHeaderFields()
        .entrySet()
        .stream()
        .map(e->String.format("key:%s value:%s", e.getKey(),e.getValue()))
        .forEach(System.out::println);
    }

    //Body情報を出力する
    private static void printBody(HttpsURLConnection con) throws Exception{
        new BufferedReader(new InputStreamReader(
                con.getInputStream()))
        .lines()
        .forEach(System.out::println);

    }
}

class NonAuthentication implements X509TrustManager {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}