1 module vksdk.client.ApiRequest; 2 3 import std.experimental.logger; 4 import std.algorithm.searching : find; 5 6 import vibe.data.json; 7 import std.json; 8 import std.conv : to; 9 10 import vksdk.client.ClientResponse; 11 import vksdk.client.TransportClient; 12 import vksdk.exceptions.ApiException; 13 import vksdk.exceptions.ClientException; 14 import vksdk.exceptions.ExceptionMapper; 15 import vksdk.objects.base.BaseError; 16 17 abstract class ApiRequest(T) { 18 19 // TODO rewrite logs 20 21 private TransportClient client; 22 23 private string url; 24 25 this(string url, TransportClient client) { 26 this.client = client; 27 this.url = url; 28 } 29 30 protected string getUrl() { 31 return url; 32 } 33 34 protected TransportClient getClient() { 35 return client; 36 } 37 38 T execute() { 39 string textResponse = executeAsString(); 40 JSONValue json = parseJSON(textResponse); 41 42 if (auto errorElement = "error" in json) { 43 BaseError error; 44 try { 45 error = deserializeJson!BaseError(errorElement.toString()); 46 } catch (Exception e) { 47 log("Invalid JSON: %s\n%s", textResponse, e.msg); 48 throw new ClientException("Can't parse json response"); 49 } 50 51 ApiException exception = ExceptionMapper.parseException(error); 52 53 log("API error: ", exception.msg); 54 throw exception; 55 } 56 57 JSONValue response = "response" in json ? json["response"] : json; 58 59 try { 60 return deserializeJson!T(response.toString()); 61 } catch (Exception e) { 62 log("Invalid JSON: %s\n%s", textResponse, e.msg); 63 throw new ClientException("Can't parse json response"); 64 } 65 } 66 67 string executeAsString() { 68 ClientResponse response; 69 try { 70 response = client.post(url, getBody()); 71 } catch (Exception e) { 72 log("Problems with request: %s\n%s", url, e.msg); 73 throw new ClientException("I/O exception"); 74 } 75 76 if (response.getStatusCode() != 200) { 77 throw new ClientException("Internal API server error. Wrong status code: " ~ to!string(response.getStatusCode) ~ ". Content: " ~ response.getContent); 78 } 79 80 if ("Content-Type" !in response.getHeaders()) { 81 throw new ClientException("No content type header"); 82 } 83 84 if (response.getHeaders()["Content-Type"].find("application/json").length > 0) { 85 throw new ClientException("Invalid content type"); 86 } 87 88 return response.getContent(); 89 } 90 91 protected abstract string getBody(); 92 }