001/* 002 * Copyright (c) 2010-2023 Mark Allen, Norbert Bartels. 003 * 004 * Permission is hereby granted, free of charge, to any person obtaining a copy 005 * of this software and associated documentation files (the "Software"), to deal 006 * in the Software without restriction, including without limitation the rights 007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 008 * copies of the Software, and to permit persons to whom the Software is 009 * furnished to do so, subject to the following conditions: 010 * 011 * The above copyright notice and this permission notice shall be included in 012 * all copies or substantial portions of the Software. 013 * 014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 020 * THE SOFTWARE. 021 */ 022package com.restfb; 023 024import static com.restfb.util.StringUtils.isBlank; 025import static com.restfb.util.StringUtils.trimToEmpty; 026import static java.lang.String.format; 027 028import java.io.IOException; 029import java.util.ArrayList; 030import java.util.List; 031import java.util.Optional; 032 033import com.restfb.util.StringUtils; 034 035/** 036 * Specifies how a class that sends {@code HTTP} requests to the Facebook API endpoint must operate. 037 * 038 * @author <a href="http://restfb.com">Mark Allen</a> 039 */ 040public interface WebRequestor { 041 /** 042 * Encapsulates an HTTP response body and status code. 043 * 044 * @author <a href="http://restfb.com">Mark Allen</a> 045 */ 046 class Response { 047 /** 048 * HTTP response status code (e.g. 200). 049 */ 050 private final Integer statusCode; 051 052 /** 053 * HTTP response body as text. 054 */ 055 private final String body; 056 057 /** 058 * Creates a response with the given HTTP status code and response body as text. 059 * 060 * @param statusCode 061 * The HTTP status code of the response. 062 * @param body 063 * The response body as text. 064 */ 065 public Response(Integer statusCode, String body) { 066 this.statusCode = statusCode; 067 this.body = trimToEmpty(body); 068 } 069 070 /** 071 * Gets the HTTP status code. 072 * 073 * @return The HTTP status code. 074 */ 075 public Integer getStatusCode() { 076 return statusCode; 077 } 078 079 /** 080 * Gets the HTTP response body as text. 081 * 082 * @return The HTTP response body as text. 083 */ 084 public String getBody() { 085 return body; 086 } 087 088 /** 089 * @see java.lang.Object#toString() 090 */ 091 @Override 092 public String toString() { 093 if (isBlank(getBody())) { 094 return format("HTTP status code %d and an empty response body.", getStatusCode()); 095 } 096 return format("HTTP status code %d and response body: %s", getStatusCode(), getBody()); 097 } 098 } 099 100 /** 101 * encapsulates the HTTP Request configuration 102 */ 103 class Request { 104 105 private final String url; 106 107 private final Optional<String> headerAccessToken; 108 109 private String parameters; 110 111 private Body body; 112 113 private List<BinaryAttachment> binaryAttachments; 114 115 /** 116 * Simple http request with url and a header access token 117 * 118 * @param url 119 * the endpoint the request ist directed to 120 * @param headerAccessToken 121 * the HTTP header access token (may be {@code null}) 122 */ 123 public Request(String url, String headerAccessToken) { 124 this(url, headerAccessToken, null); 125 } 126 127 /** 128 * Simple http request with url and a header access token 129 * 130 * @param url 131 * the endpoint the request ist directed to 132 * @param headerAccessToken 133 * the HTTP header access token (may be {@code null}) 134 * @param parameters 135 * the query parameter string 136 */ 137 public Request(String url, String headerAccessToken, String parameters) { 138 this(url, headerAccessToken, parameters, null); 139 } 140 141 /** 142 * Simple http request with url and a header access token 143 * 144 * @param url 145 * the endpoint the request ist directed to 146 * @param headerAccessToken 147 * the HTTP header access token (may be {@code null}) 148 * @param parameters 149 * the query parameter string 150 * @param attachments 151 * list of binary attachments 152 */ 153 public Request(String url, String headerAccessToken, String parameters, List<BinaryAttachment> attachments) { 154 this.url = url; 155 this.headerAccessToken = Optional.ofNullable(headerAccessToken); 156 this.parameters = parameters; 157 setBinaryAttachments(attachments); 158 } 159 160 public String getUrl() { 161 return url; 162 } 163 164 public String getHeaderAccessToken() { 165 return headerAccessToken.orElse(null); 166 } 167 168 public boolean hasHeaderAccessToken() { 169 return headerAccessToken.isPresent(); 170 } 171 172 public String getParameters() { 173 return parameters; 174 } 175 176 public List<BinaryAttachment> getBinaryAttachments() { 177 return Optional.ofNullable(binaryAttachments).orElse(new ArrayList<>()); 178 } 179 180 public void setBinaryAttachments(List<BinaryAttachment> binaryAttachments) { 181 this.binaryAttachments = Optional.ofNullable(binaryAttachments).orElse(new ArrayList<>()); 182 } 183 184 public String getFullUrl() { 185 if (!StringUtils.isBlank(parameters)) { 186 if (url != null && url.contains("?")) { 187 return url + "&" + parameters; 188 } 189 return url + "?" + parameters; 190 } 191 return url; 192 } 193 194 @Override 195 public String toString() { 196 return format("Request to url %s with parameters %s. Header access token: %b", getUrl(), getParameters(), 197 hasHeaderAccessToken()); 198 } 199 200 public void setBody(Body body) { 201 this.body = body; 202 } 203 204 public Body getBody() { 205 return body; 206 } 207 208 public boolean hasBody() { 209 return body != null; 210 } 211 } 212 213 /** 214 * Given a Facebook API endpoint URL, execute a {@code GET} against it. 215 * 216 * @param request 217 * The request data for the {@code GET} request 218 * @return HTTP response data. 219 * @throws IOException 220 * If an error occurs while performing the {@code GET} operation. 221 * @since 1.5 222 */ 223 Response executeGet(Request request) throws IOException; 224 225 /** 226 * Given a Facebook API endpoint URL and parameter string, execute a {@code POST} to the endpoint URL. 227 * 228 * @param request 229 * The request data used for the {@code POST} request. 230 * @return HTTP response data. 231 * @throws IOException 232 * If an error occurs while performing the {@code POST}. 233 */ 234 Response executePost(Request request) throws IOException; 235 236 /** 237 * Given a Facebook API endpoint URL and parameter string, execute a {@code DELETE} to the endpoint URL. 238 * 239 * @param request 240 * The request data used for the {@code DELETE} request. 241 * @return HTTP response data. 242 * @throws IOException 243 * If an error occurs while performing the {@code DELETE}. 244 */ 245 Response executeDelete(Request request) throws IOException; 246 247 /** 248 * Provides access to the facebook header information. 249 * 250 * The fields <code>x-fb-rev</code>, <code>x-fb-trace-id</code> and <code>x-fb-debug</code> are checked and returned 251 * in a single container of the type {@link DebugHeaderInfo} 252 * 253 * @return container with the explained facebook debug header information 254 */ 255 DebugHeaderInfo getDebugHeaderInfo(); 256}