001/*
002 * Stallion Core: A Modern Web Framework
003 *
004 * Copyright (C) 2015 - 2016 Stallion Software LLC.
005 *
006 * This program is free software: you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation, either version 2 of
008 * the License, or (at your option) any later version. This program is distributed in the hope that
009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
011 * License for more details. You should have received a copy of the GNU General Public License
012 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
013 *
014 *
015 *
016 */
017
018package io.stallion.requests;
019
020import io.stallion.plugins.javascript.Sandbox;
021import io.stallion.services.Log;
022import io.stallion.users.IOrg;
023import io.stallion.users.IUser;
024import org.eclipse.jetty.server.Request;
025
026import javax.servlet.MultipartConfigElement;
027import javax.servlet.http.Cookie;
028import javax.servlet.http.HttpServletRequest;
029import javax.servlet.http.Part;
030import java.io.BufferedReader;
031import java.io.IOException;
032import java.io.UnsupportedEncodingException;
033import java.net.URI;
034import java.net.URISyntaxException;
035import java.net.URLDecoder;
036import java.util.Enumeration;
037import java.util.List;
038import java.util.Map;
039import java.util.Set;
040
041import static io.stallion.utils.Literals.empty;
042import static io.stallion.utils.Literals.list;
043
044public interface IRequest {
045    public static final String RECENT_POSTBACK_COOKIE = "st-recent-postback";
046
047
048    public default void setAsMultiPartRequest() {
049
050    }
051
052    public default Part getPart(String name) {
053        return null;
054    }
055
056    public default HttpServletRequest getHttpServletRequest() {
057        return null;
058    }
059
060    /**
061     * Get the full, externally facing URL used to intiate this request.
062     *
063     * @return
064     */
065    public String requestUrl();
066
067    /**
068     * Alis for requestUrl()
069     * @return
070     */
071    public default String getRequestUrl() {
072        return requestUrl();
073    }
074
075    public String getScheme();
076
077
078    public default URI getRequestUri() {
079        try {
080            return new URI(requestUrl());
081        } catch (URISyntaxException e) {
082            throw new RuntimeException(e);
083        }
084    }
085
086
087    /**
088     * Absolute URL of the request with the query string.
089     */
090    public default String getRequestUrlWithQuery() {
091        String url = requestUrl();
092        if (!empty(getQueryString())) {
093            url += "?" + getQueryString();
094        }
095        return url;
096    }
097
098    /**
099     * Get the request query string, everything after the ? in the URL
100     *
101     * @return
102     */
103    public String getQueryString();
104
105    public default List<String> getQueryParamAsList(String key) {
106        List<String> values = list();
107        String[] pairs = getQueryString().split("&");
108        for (String pair : pairs) {
109            int idx = pair.indexOf("=");
110            if (idx < 0) {
111                continue;
112            }
113            try {
114                String name = URLDecoder.decode(pair.substring(0, idx), "UTF-8");
115                if (name.equals(key)) {
116                    values.add(URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
117                }
118            } catch (UnsupportedEncodingException e) {
119                Log.exception(e, "Error parsing url {0}", getQueryString());
120            }
121        }
122        return values;
123    }
124
125    /**
126     * Get the RemoteAddr field from the underlying HttpServletRequest object,
127     * which gets it from the socket connection. Note that if you have nginx
128     * running as a proxy in front of Stallion, then remoteAddr will be localhost,
129     * since the socket connection is coming from Nginx. If you have a load balancer
130     * in front of Stallion, the remoteAddr will be of the load balancer
131     *
132     * @return
133     */
134    public String getRemoteAddr();
135
136
137    /**
138     * Gets the host by first looking for the x-forwarded-for header, and then
139     * the Host: header.
140     *
141     * @return
142     */
143    public String getHost();
144
145    /**
146     * Tries to guess the actual IP address of the end-user, by looking at the
147     * IP address header as defined in settings.ipHeaderName (x-real-ip by default) and
148     * then getRemoteAddr() if the header does not exist.
149     *
150     * @return
151     */
152    public String getActualIp();
153
154    /**
155     * Interpret the body of the request as JSON and parse it into the given object.
156     *
157     * @param clazz
158     * @return
159     */
160    public Object getBodyObject(Class clazz);
161
162    /**
163     * Parse the request body based on the content-type, usually either form encoded or JSON,
164     * and then parse it into a Map
165     *
166     * @return
167     */
168    public Map<String, Object> getBodyMap();
169
170    /**
171     * Internally, gets the request body as Map, and then returns the value for the given key
172     *
173     * @param name
174     * @return
175     */
176    public Object getBodyParam(String name);
177
178    /**
179     * Parses the query string into a map
180     *
181     * @return
182     */
183    public Map<String, String> getQueryParams();
184
185    public Cookie[] getCookies();
186
187    public Cookie getCookie(String cookieName);
188
189    /**
190     * Get the request path
191     *
192     * @return
193     */
194    public String getPath();
195
196
197    public void setPath(String path);
198
199    /**
200     * Get the given request header, case insensitive
201     * @param name
202     * @return
203     */
204    public String getHeader(String name);
205
206    /**
207     * Get a Reader that reads the request body
208     *
209     * @return
210     * @throws IOException
211     */
212    public BufferedReader getReader() throws IOException;
213
214    /**
215     * Gets the request body as a string
216     *
217     * @return
218     */
219    public String getContent();
220
221    public Enumeration<String> getHeaderNames();
222
223    /**
224     * Gets the user associated with the current request
225     *
226     * @return
227     */
228    public IUser getUser();
229
230    public void setUser(IUser user);
231
232    public IOrg getOrg();
233
234    public void setOrg(IOrg org);
235
236    /**
237     * Gets the HTTP method - GET, POST, PUT, DELETE, etc.
238     * @return
239     */
240    public String getMethod();
241
242    /**
243     * Gets the parameter from either the query string or the request body
244     * @param paramName
245     * @return
246     */
247    public String getParameter(String paramName);
248
249    /**
250     * Returns true if this request is expected to produce JSON, used to determine
251     * what kind of response to give in cases of errors.
252     *
253     * @return
254     */
255    public Boolean getIsJsonRequest();
256
257    public void setIsJsonRequest(Boolean isJsonRequest);
258
259
260    public void setQuery(String query);
261
262    /**
263     * Get an arbitrary hashmap of data that lives the lifetime of this request,
264     * can be used as a very short lived cache, or for any other arbitrary use.
265     *
266     * @return
267     */
268    public Map<String, Object> getItems();
269
270    public void setItems(Map<String, Object> items);
271
272    /**
273     * Get a sandboxed version of this request object. Sandboxing usually limits
274     * access to the headers and cookies, so that a plugin cannot steal authentication
275     * tokens.
276     *
277     * @param box
278     * @return
279     */
280    public SandboxedRequest getSandboxedRequest(Sandbox box);
281
282    /**
283     * If this is a scoped, OAuth request, return the scopes.
284     * @return
285     */
286    public Set<String> getScopes();
287
288    public IRequest setScopes(Set<String> scopes);
289
290    /**
291     * Return true if this is scope-limited OAuth request
292     * @return
293     */
294    public boolean isScoped();
295
296    public IRequest setScoped(boolean scoped);
297}