Як висміювати складний виклик REST зі сторони сервера?

Під час роботи з JavaScript, який широко використовує служби REST, - включаючи використання vocab, таких як GET, PUT, POST, DELETE та ін; Я вважаю, що важко висміювати сторону сервера, тому розвиток інтерфейсу може йти незалежно (від заднього кінця).

Також корисно іноді знімати багатоступеневі дані, тому ми можемо допомогти відтворити навіть весь ланцюжок REST (або помилки, пов'язані з інтерфейсом, які викликаються з цих ланцюгів)

Які інструменти я можу використовувати, щоб придушити дзвінки REST, ESP державні? (скажімо, якщо я роблю PUT на деякому ресурсі, я сподіваюся, що наступний GET на нього якось змінити)

Я спробував SOAPUI 4.0.1 і розгублення REST це розчаровує. Крім того, моя потреба полягає в тому, щоб не роздумувати про єдиний державний стан (який кожен може зробити зі статичним файлом .json). Мені потрібно зробити державний тип перехоплення; Найкраще буде працювати з заголовками Content-Range.

Хтось?

7

2 Відповіді

Ось інший індивідуальний інструмент для розваги: ​​ https://github.com/mkotsur/restito .

3
додано

Я насправді закінчив створювати свій власний Java REST Mock Engine, який в основному може придушити будь-яку відповідь. Поки ви можете виконувати обробку або вилучити текстовий файл, який імітує всю http-відповідь, ви можете використовувати моє рішення для придушення служби.

Ось сервлет:

package com.mockrest.debug;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class MockGridData
 */
public class MockRest extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public MockRest() {
        super();
       //TODO Auto-generated constructor stub
    }

    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        sub:{
            HttpServletRequest request = (HttpServletRequest)req;
            HttpServletResponse response = (HttpServletResponse)res;
            String setdata = request.getParameter("__setdata");
            if (setdata!=null && setdata.length()>0){
                System.err.println("Setting Data...");
                HttpSession sess = request.getSession(true);
                String data = "/"+request.getParameter("__setdata");
                sess.setAttribute("data", data);
                try{
                    InputStream is = getServletContext().getResourceAsStream(data);
                    if (is!=null){
                        is.close();
                        response.getWriter().write("Successfully pointed next REST call to:"+data);
                    }
                    else{
                        response.sendError(500, "Cannot find resource:"+data);
                    }
                }
                catch (IOException ioe){
                    response.sendError(500, Arrays.deepToString(ioe.getStackTrace()));
                }

            }
            else{
                System.err.println("Fetching Data...");
                HttpSession sess = request.getSession(false);
                if (sess==null || sess.getAttribute("data")==null){
                    response.sendError(500,"Session invalid or no Previous Data Set!");
                }
                String rsrc = (String)sess.getAttribute("data");
                System.err.println("Resource Being used:"+rsrc);
                InputStream is = getServletContext().getResourceAsStream(rsrc);
                if (is!=null){
                    String statusline = readLine(is);
                    Pattern statusPat = Pattern.compile("^HTTP/1.1 ([0-9]+) (.*)$");
                    Matcher m = statusPat.matcher(statusline);
                    if (m!=null && m.matches()){
                        int status = Integer.valueOf(m.group(1));
                        response.setStatus(status, m.group(2));
                    }
                    else{
                        throw new ServletException("Bad input file: status line parsing failed, got this as status line:"+statusline);
                    }
                    String line;
                    Pattern httpHeaderPat = Pattern.compile("^([^:]+): (.*)$");
                    while ((line=readLine(is))!=null){
                        if (line.length()==0){
                           //end of headers
                            break;
                        }
                        Matcher m2 = httpHeaderPat.matcher(line);
                        if (m2!=null && m2.matches()){
                            response.setHeader(m2.group(1), m2.group(2));
                        }
                    }
                    OutputStream os = response.getOutputStream();
                    byte[] buf = new byte[1024];
                    int size;
                    while ((size=is.read(buf))>0){
                        os.write(buf, 0, size);
                    }
                    os.flush();
                }
            }
        }
    }

    private String readLine(InputStream is) throws IOException {
        StringBuffer sb = new StringBuffer();
        char c;
        while ((c=(char)is.read())!='\n'){
            sb.append(c);
        }
        if (sb.charAt(sb.length()-1) == '\r'){
            sb.deleteCharAt(sb.length()-1);
        }
        return sb.toString();
    }

}

Щоб налаштувати його, помістіть попередньо встановлені файли відповідей у ​​папку WebContent . Зазвичай ці файли закінчуються розширеннями .http .

Нижче наведено приклад файлу init.http . Представляємо, що ми розмістили цей файл всередині папки під назвою data </​​code> всередині WebContent:

HTTP/1.1 200 OK
Date: Wed, 26 Oct 2011 18:31:45 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 4.0.30319
Content-Range: items 0-1/2
Content-Length: 385
Cache-Control: private
Content-Type: application/json

[
  {
    "id": "249F0",
    "field1": " Global",
    "displaystartdate": "2007-10-20",
    "displayenddate": "2012-10-20",
    "status": "Major Delay",
    "children": true
  },
  {
    "id": "962581",
    "field2": "Europe",
    "displaystartdate": "2007-10-20",
    "displayenddate": "2012-10-20",
    "status": "Major Delay",
    "children": true
  }
]

Заголовки повинні розділяти тіло на порожній рядок (без пробілів, nada). Люди, які знайомі з http, помічають, що це чистий http-відповідь. Це цілеспрямовано.

Ви можете використовувати цей інструмент для імітації будь-якого заголовка http, який ви хочете отримати відповідь; навіть наближаючись до відповіді на інший серверний заголовок (у моєму прикладі, я імітував відповідь, прикидаючись, що це IIS 6.0); або інший код статусу HTTP тощо.

Щоб викликати це з вашого браузера/javascript; спочатку приминіть це з:

http://yourserver/yourweb/MockGridData?__setdata=data/init.http

Потім у вашому Javascript або REST AJAX виклик, якщо він йде

http://yourserver/yourweb/MockGridData

з будь-яким методом або параметром; він отримає http-відповідь, яку ви раніше створили; навіть до діапазону вмісту; Заголовки кешу; тощо. Якщо вам потрібен наступний дзвінок AJAX, щоб повернути щось інше, просто зателефонуйте знову за допомогою __ setdata </​​code>. Я пропоную вам налаштувати кілька кнопок, щоб зробити явний перехід у вашому веб-додатку.

Припускаючи, що все налаштовано, для моделюється ланцюжка REST розробник може:

  1. invoke

    http://yourserver/yourweb/MockGridData?__setdata=data/init.http
    
  2. run a JavaScript module that will result in calling (say, with GET)

    http://yourserver/yourweb/MockGridData
    
  3. click a button that then does:

    http://yourserver/yourweb/MockGridData?__setdata=data/step1.http
    
  4. run another JavaScript step that will result in calling (say, with PUT)

    http://yourserver/yourweb/MockGridData
    
  5. click another button that then does:

    http://yourserver/yourweb/MockGridData?__setdata=data/step2.http
    
  6. run another JavaScript step that will result in calling (say, with GET)

    http://yourserver/yourweb/MockGridData
    

    but this time expecting different result than #4.

Це повинно навіть працювати з бінарними та gzip-відповідями, але я не протестував це.

2
додано
Вітаю з рішенням. Коли зможете, будь ласка, обов'язково позначте свою відповідь "прийнятою", щоб інші могли навчитися у вас успіху. Ура!
додано Автор Andrew Kozak, джерело