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 }