Jak korzystać z GitHub API
Jak korzystać z GitHub API
GitHub wystawia własne API które dostarcza wielu cennych informacji o repozytoriach. W artykule tym wystawimy własne API które z użyciem API GitHuba dostarczy informacji o konkretnym repozytorium. Zaczynamy od nowego projektu Spring Boot – niezbędne zależności – plik pom.xml:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.6</version> </dependency> <dependency> <groupId>one.util</groupId> <artifactId>streamex</artifactId> <version>0.6.5</version> </dependency> </dependencies>
Tworzymy model – GitHubEntity:
public class GitHubEntity { @JsonProperty("fullName") private String nameOfRepository; @JsonProperty("description") private String descriptionOfRepository; @JsonProperty("cloneUrl") private String gitCloneUrlRepository; @JsonProperty("stars") private Integer numberOfStargazerRepository; @JsonProperty("createdAt") private String dateOfCreationRepository; // setters & getters }
RestController – wystawiamy własne API i korzystamy z biblioteki gson:
@RestController @RequestMapping("/repositories") public class GithubControllerRestApiController { @RequestMapping("/{owner}/{repositoryName}") public ResponseEntity<?> getRepoDetailsByOwner(@PathVariable String owner, @PathVariable String repositoryName) { final String FULL_NAME = "full_name"; final String DESCRIPTION = "description"; final String CLONE_URL = "clone_url"; final String CREATED_AT = "created_at"; Map map = getMapFromJson(githubWrapperRepo(owner,repositoryName)); String fullNameRepo = map.get(FULL_NAME).toString(); String descriptionRepo = map.get(DESCRIPTION).toString(); String cloneUrlRepo = map.get(CLONE_URL).toString(); String createdDateRepo = map.get(CREATED_AT).toString(); int stars = githubWrapperStarGazersQuantity(owner,repositoryName); return new ResponseEntity(createModel(fullNameRepo,descriptionRepo,cloneUrlRepo,createdDateRepo, stars), httptatus.OK); } private int githubWrapperStarGazersQuantity(String user, String repo) { HttpEntity<String> entity = new HttpEntity("parameters", GitHubHelper.getUserAgentHeader()); RestTemplate rest = new RestTemplate(); ResponseEntity<String> exchange = rest.exchange( "http://api.github.com/repos/" + user + "/" + repo + "/stargazers", HttpMethod.GET, entity, String.class); return getGson().fromJson(exchange.getBody(), Map[] .class).length; } private String githubWrapperRepo(String user, String repo) { HttpEntity<String> entity = new HttpEntity("parameters", GitHubHelper.getUserAgentHeader()); RestTemplate rest = new RestTemplate(); ResponseEntity<String> exchange = rest.exchange( "http://api.github.com/repos/" + user + "/" + repo, HttpMethod.GET, entity, String.class); return exchange.getBody(); } private Gson getGson() { return new Gson(); } private Map getMapFromJson(String jsonString) { return getGson().fromJson(jsonString, Map.class); } private GitHubEntity createModel(String fullNameRepo,String descriptionRepo, String cloneUrlRepo, String createdDateRepo, int stars) { GitHubEntity gitHubEntity = new GitHubEntity(); gitHubEntity.setNameOfRepository(fullNameRepo); gitHubEntity.setDescriptionOfRepository(descriptionRepo); gitHubEntity.setGitCloneUrlRepository(cloneUrlRepo); gitHubEntity.setNumberOfStargazerRepository(stars); gitHubEntity.setDateOfCreationRepository(createLocalDate(createdDateRepo)); return gitHubEntity; } private String createLocalDate(String createdDateRepo) { ZonedDateTime zonedDateTime = ZonedDateTime.parse(createdDateRepo); return zonedDateTime.toLocalDate().toString(); } }
Odpowiedni Helper który doda nagłówek User-Agent co jest wymagane przez API GitHuba:
public class GitHubHelper { public static HttpHeaders getUserAgentHeader() { HttpHeaders headers = new HttpHeaders(); headers.add("User-Agent", "http://developer.github.com/v3/#user-agent-required"); return headers; } }
Mapowanie wyniku żądania na model:
public class RetrieveUtil { public static <T> T retrieveResourceFromResponse(HttpResponse response, Class<T> clazz) throws IOException { String jsonFromResponse = EntityUtils.toString(response.getEntity()); ObjectMapper mapper = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); return mapper.readValue(jsonFromResponse, clazz); } }
Testy jednostkowe – spring-boot-starter-test. Weryfikujemy status odpowiedzi oraz weryfikujemy nazwę repozytorium:
@RunWith(SpringRunner.class) @SpringBootTest public class GithubRestWrapperApiApplicationTests { @Test public void contextLoads() { } @Test public void checkStatusCode() throws IOException { // Given HttpUriRequest request = new HttpGet( "http://localhost:8080//repositories/mwarycha/SpringMVC4"); // When HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request); // Then assertThat(httpResponse.getStatusLine().getStatusCode(), equalTo(httptatus.SC_OK)); } @Test public void checkNameOfRepository() throws IOException { // Given HttpUriRequest request = new HttpGet( "http://localhost:8080//repositories/mwarycha/SpringMVC4" ); // When HttpResponse response = HttpClientBuilder.create().build().execute( request ); // Then GitHubEntity resource = RetrieveUtil.retrieveResourceFromResponse(response, GitHubEntity.class); assertThat( "mwarycha/SpringMVC4", Matchers.is(resource.getNameOfRepository())); } }
Wyniki testów:
[INFO] [INFO] Results: [INFO] [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 22.607 s [INFO] Finished at: 2019-07-30T17:52:29+02:00 [INFO] ------------------------------------------------------------------------
Leave a comment