1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*!
Response types for the Elasticsearch REST API.

All [high-level builders][request-builders] return one of these response types for you.
This module also contains helpers that can be used to parse responses from a raw [`HttpResponse`][HttpResponse].

[HttpResponse]: struct.HttpResponse.html
[request-builders]: ../index.html#request-builders
*/

pub mod parse;

use std::io::{Read, Result as IoResult};
use serde::de::DeserializeOwned;
use elastic_reqwest::ParseResponse;
use elastic_reqwest::res::parse;
use reqwest::Response as RawResponse;

use error::*;
use client::IntoResponseBuilder;
use self::parse::IsOk;

pub use elastic_reqwest::res::{SearchResponseOf, GetResponseOf, AggregationIterator, Aggregations,
                               Hit, Hits, Shards, CommandResponse, IndexResponse, PingResponse,
                               BulkResponse, BulkErrorsResponse, BulkItem, BulkItems,
                               BulkItemError, BulkAction};
/**
A builder for a response.

This structure wraps the completed HTTP response but gives you options for converting it into a concrete type.
You can also `Read` directly from the response body.
*/
pub struct ResponseBuilder(RawResponse);

impl Into<ResponseBuilder> for IntoResponseBuilder {
    fn into(self) -> ResponseBuilder {
        ResponseBuilder(self.0)
    }
}

impl ResponseBuilder {
    /** Get the HTTP status for the response. */
    pub fn status(&self) -> u16 {
        self.0.status().to_u16()
    }

    /**
    Get the response body from JSON.
    
    Convert the builder into a raw HTTP response that implements `Read`.
    */
    pub fn into_raw(self) -> HttpResponse {
        HttpResponse(self.0)
    }

    /**
    Parse an API response type from the HTTP body.
    
    This will consume the `ResponseBuilder` and return a [concrete response type][response-types] or an error.
    
    The response is parsed according to the `IsOk` implementation for `T` that will inspect the response and either return an `Ok(T)` or an `Err(ApiError)`.
    
    # Examples
    
    Get a strongly typed `SearchResponse`:
    
    ```no_run
    # extern crate serde;
    # #[macro_use]
    # extern crate serde_derive;
    # #[macro_use]
    # extern crate elastic_derive;
    # extern crate elastic;
    # use elastic::prelude::*;
    # fn main() {
    # #[derive(Serialize, Deserialize, ElasticType)]
    # struct MyType {
    #     pub id: i32,
    #     pub title: String,
    #     pub timestamp: Date<DefaultDateFormat>
    # }
    # let params = RequestParams::new("http://es_host:9200");
    # let client = Client::new(params).unwrap();
    # let req = PingRequest::new();
    let response = client.request(req)
                         .send()
                         .and_then(into_response::<SearchResponse<MyType>>);
    # }
    ```
    
    You can also read a response as a `serde_json::Value`, which will be `Ok(Value)`
    if the HTTP status code is `Ok` or `Err(ApiError)` otherwise:
    
    ```no_run
    # extern crate elastic;
    # extern crate serde_json;
    # use serde_json::Value;
    # use elastic::prelude::*;
    # fn main() {
    # let params = RequestParams::default();
    # let client = Client::new(params).unwrap();
    # let req = PingRequest::new();
    let response = client.request(req)
                         .send()
                         .and_then(into_response::<Value>);
    # }
    ```

    [response-types]: parse/trait.IsOk.html#implementors
    */
    pub fn into_response<T>(self) -> Result<T>
        where T: IsOk + DeserializeOwned
    {
        parse().from_response(self.0).map_err(Into::into)
    }
}

/**
A generic Search API response.

For responses that contain multiple document types, use `SearchResponse<serde_json::Value>`.

This type won't parse if you've applied any [response filters][docs-response-filtering].
If you need to tweak the shape of the search response you can define your own response type and implement `IsOk` for it.
See the [`parse`][parse-mod] mod for more details.

[parse-mod]: parse/index.html
[docs-response-filtering]: https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#common-options-response-filtering
*/
pub type SearchResponse<T> = SearchResponseOf<Hit<T>>;

/** A generic Get Document API response. */
pub type GetResponse<T> = GetResponseOf<T>;

/** A raw HTTP response that can be buffered using `Read`. */
pub struct HttpResponse(RawResponse);

impl HttpResponse {
    /** Get the HTTP status for the response. */
    pub fn status(&self) -> u16 {
        self.0.status().to_u16()
    }
}

impl Read for HttpResponse {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        self.0.read(buf)
    }
}