Угловой $ http.delete + hapijs с использованием swagger + grails

0

У меня есть клиент с угловыми, глотками, хапиями и чванством. Этот клиент подключается к моему WS, работающему на grails. У этого WS есть Swagger.json.

Проблема в том, что я не могу удалить автора. Я не знаю, как это неправильно.

Мой угловой завод

(function () {
    'use strict';

    angular
        .module('qrbweb')
        .factory('AuthorFactory', ['$http', AuthorFactory]);

    function AuthorFactory($http) {

        var authors = [];

        return {
            list: function () {
                $http.get("http://localhost:3000/authors").then(function (response) {
                    authors = response.data;
                });
            },
            delete: function (id) {
                console.log(id)
                $http.delete("http://localhost:3000/authors/" + id)
                    .success(function (result) {
                        console.log(result);
                    }).error(function () {
                        console.log("error");
                    });
            },
            get: function () {
                return authors;
            }
        };
    }
})();

Мой index.js из hapijs

var hapi = require('hapi');
var server = new hapi.Server();
var intert = require('inert');

server.connection({port: 3000});

server.register(intert, function () {
});

server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {
        directory: {
            path: 'src/client/main/',
            redirectToSlash: true,
            index: true
        }
    }
});

server.route({
    method: 'GET',
    path: '/author/{params*}',
    handler: {
        directory: {
            path: 'src/client/main/app/components/author/list/author.list.html'
        }
    }
});

server.route({
    method: 'GET',
    path: '/bower_components/{params*}',
    handler: {
        directory: {
            path: 'bower_components/'
        }
    }
});

server.route({
    method: 'GET',
    path: '/app/{params*}',
    handler: {
        directory: {
            path: 'src/client/main/app/'
        }
    }
});

/**
 * Dynamic routes
 */
var client = require('swagger-client');

server.route({
        method: 'GET',
        path: '/authors/{param*}',
        handler: function (request, reply) {
            var swagger = new client({
                url: 'http://localhost:8080/swagger.json',
                success: function () {
                    swagger.author.list({max: 10, offset: 0}, function (response) {
                        reply(response.data).type('application/json')
                    });
                }
            });
        }
    }
);

server.route({
        method: 'delete',
        path: '/authors/{id}',
        handler: function (request, reply) {
            var swagger = new client({
                url: 'http://localhost:8080/swagger.json',
                success: function () {
                    swagger.author.delete({authorId: request.params.id}, function (response) {
                        reply(response.data).type('application/json')
                    });
                }
            });
        }
    }
);

server.start(function () {
    console.log('Running server at ', server.info.uri);
});

Swagger.json

{
  "swagger": "2.0",
  "info": {
    "version": "1.0.0",
    "title": "Swagger QRBWS",
    "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
    "termsOfService": "http://swagger.io/terms/",
    "contact": {
      "name": "Swagger API Team"
    },
    "license": {
      "name": "MIT"
    }
  },
  "host": "localhost:8080",
  "basePath": "/api",
  "schemes": [
    "http"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/author": {
      "get": {
        "tags": [
          "author"
        ],
        "operationId": "list",
        "description": "Returns all pets from the system that the user has access to",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "max",
            "in": "query",
            "description": "The maximum number to list",
            "type": "integer",
            "default": 10,
            "minimum": 1,
            "maximum": 100
          },
          {
            "name": "offset",
            "in": "query",
            "description": "The offset from the first result to list from",
            "type": "integer",
            "default": 0,
            "minimum": 0
          }
        ],
        "responses": {
          "200": {
            "description": "A list of pets.",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Author"
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "author"
        ],
        "summary": "Delete purchase order by ID",
        "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors",
        "operationId": "delete",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "authorId",
            "description": "Pet id to delete",
            "required": true,
            "type": "test",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    }
  },
  "definitions": {
    "Author": {
      "type": "object",
      "required": [
        "id",
        "name",
        "notes"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        }
      }
    }
  }
}

Когда я отправляю запрос на удаление автора, это генерируется:

Request URL:http://localhost:3000/authors/9 
Request Headers Provisional headers are shown
Accept:application/json,text/plain, */*
Origin:http://localhost:3000 
Referer:http://localhost:3000/author 
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36

И это ошибка:

{ url: 'http://localhost:8080/api/author?authorId=8',   method: 'DELETE',   headers:     { server: 'Apache-Coyote/1.1',
     'x-application-context': 'application:development',
     allow: 'HEAD, GET',
     'content-type': 'application/json;charset=UTF-8',
     'transfer-encoding': 'chunked',
     date: 'Thu, 20 Aug 2015 05:31:36 GMT',
     connection: 'close' },   obj:     { [Error: Method Not Allowed]
     original: null,
     response: 
      { domain: [Object],
        _events: {},
        _maxListeners: undefined,
        res: [Object],
        request: [Object],
        req: [Object],
        links: {},
        text: '{"timestamp":1440048697000,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method \'DELETE\' not supported","path":"/api/author"}',
        body: [Object],
        files: {},
        buffered: true,
        headers: [Object],
        header: [Object],
        statusCode: 405,
        status: 405,
        statusType: 4,
        info: false,
        ok: false,
        redirect: false,
        clientError: true,
        serverError: false,
        error: [Object],
        accepted: false,
        noContent: false,
        badRequest: false,
        unauthorized: false,
        notAcceptable: false,
        forbidden: false,
        notFound: false,
        charset: 'UTF-8',
        type: 'application/json',
        setEncoding: [Function],
        redirects: [] },
     status: 405 },   status: 405,   statusText: '{"timestamp":1440048697000,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method \'DELETE\' not supported","path":"/api/author"}',   data: '{"timestamp":1440048697000,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method \'DELETE\' not supported","path":"/api/author"}' }
  • 1
    Какой код для метода удаления в контроллере автора Grails?
  • 0
    Я использую ресурсы: pastebin.com/h0Up2JhU Работает, если отправить запрос (тип DELETE) непосредственно для моего WS: localhost: 8080 / api / author
Теги:
swagger
hapijs
grails

3 ответа

1

Ну, я ищу решения и закончу создание своего собственного интегратора для клиента Swagger Specification 2.0 для AngularJS 1. 4+

Вы можете узнать больше об этом здесь: https://github.com/olaferlandsen/angular-swagger2-client

Некоторые функции:

  • Запросы POST, PUT, GET, DELETE, PATCH и CONNECT поддерживаются.
  • Params in: query, path, formData и заголовок поддерживаются.
  • Поддерживается SecuritySchema с поддержкой безопасности в API (только тип apiKey).
  • По умолчанию запрос PUT и POST отправляется с типом контента: application/x-www-form-urlencoded; кодировка = UTF-8.
  • Удаляет все параметры, которые не были установлены в определении API.
  • Внедряет предварительный валидатор для параметров и поддерживаемых типов данных, их формата и необходимости.
  • Глобальное статическое и динамическое значение по умолчанию, основанное на LocalStorage.
0

Мой swagger.json был неправ, это правильно:

{   "swagger": "2.0",   "info": {
    "version": "1.0.0",
    "title": "Swagger QRBWS",
    "description": "API of QRBWS",
    "termsOfService": "https://github.com/felansu/QRBWS/blob/master/README.md",
    "contact": {
      "name": "Ferran Gonzalez Alonso",
      "url": "https://github.com/felansu/QRBWS/",
      "email": "[email protected]"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
    }   },   "host": "localhost:8080",   "basePath": "/api",   "schemes": [
    "http",
    "https"   ],   "consumes": [
    "application/json"   ],   "produces": [
    "application/json"   ],   "paths": {
    "/author/": {
      "get": {
        "tags": [
          "author"
        ],
        "operationId": "list",
        "description": "Returns all authors",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "max",
            "in": "query",
            "description": "The maximum number to list",
            "type": "integer",
            "default": 10,
            "minimum": 1,
            "maximum": 100
          },
          {
            "name": "offset",
            "in": "query",
            "description": "The offset from the first result to list from",
            "type": "integer",
            "default": 0,
            "minimum": 0
          }
        ],
        "responses": {
          "200": {
            "description": "A list of authors.",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Author"
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "author"
        ],
        "summary": "Create",
        "description": "Create an author",
        "operationId": "create",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "author",
            "description": "Author object",
            "required": true,
            "schema": {
              "items": {
                "$ref": "#/definitions/Author"
              }
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid params supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    },
    "/author/{authorId}": {
      "get": {
        "tags": [
          "author"
        ],
        "summary": "Get an author",
        "description": "For valid response an author with authorId param should be exist",
        "operationId": "getById",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "authorId",
            "description": "Author id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      },
      "delete": {
        "tags": [
          "author"
        ],
        "summary": "Delete an author",
        "description": "For valid response an author with authorId param should be exist",
        "operationId": "delete",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "authorId",
            "description": "Author id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      },
      "put": {
        "tags": [
          "author"
        ],
        "summary": "Update",
        "description": "Update an author",
        "operationId": "update",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "author",
            "description": "Author object",
            "required": true,
            "schema": {
              "items": {
                "$ref": "#/definitions/Author"
              }
            }
          },
          {
            "in": "path",
            "name": "authorId",
            "description": "Author id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid params supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    },
    "/category/": {
      "get": {
        "tags": [
          "category"
        ],
        "operationId": "list",
        "description": "Returns all categories",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "max",
            "in": "query",
            "description": "The maximum number to list",
            "type": "integer",
            "default": 10,
            "minimum": 1,
            "maximum": 100
          },
          {
            "name": "offset",
            "in": "query",
            "description": "The offset from the first result to list from",
            "type": "integer",
            "default": 0,
            "minimum": 0
          }
        ],
        "responses": {
          "200": {
            "description": "A list of categories.",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Category"
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "category"
        ],
        "summary": "Create",
        "description": "Create an category",
        "operationId": "create",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "category",
            "description": "Category object",
            "required": true,
            "schema": {
              "items": {
                "$ref": "#/definitions/Category"
              }
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid params supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    },
    "/category/{categoryId}": {
      "get": {
        "tags": [
          "category"
        ],
        "summary": "Get an category",
        "description": "For valid response an category with categoryId param should be exist",
        "operationId": "getById",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "categoryId",
            "description": "Author id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      },
      "delete": {
        "tags": [
          "category"
        ],
        "summary": "Delete an category",
        "description": "For valid response an category with categoryId param should be exist",
        "operationId": "delete",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "categoryId",
            "description": "Author id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      },
      "put": {
        "tags": [
          "category"
        ],
        "summary": "Update",
        "description": "Update an category",
        "operationId": "update",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "category",
            "description": "Author object",
            "required": true,
            "schema": {
              "items": {
                "$ref": "#/definitions/Author"
              }
            }
          },
          {
            "in": "path",
            "name": "categoryId",
            "description": "Author id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid params supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    },
    "/idiom/": {
      "get": {
        "tags": [
          "idiom"
        ],
        "operationId": "list",
        "description": "Returns all categories",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "max",
            "in": "query",
            "description": "The maximum number to list",
            "type": "integer",
            "default": 10,
            "minimum": 1,
            "maximum": 100
          },
          {
            "name": "offset",
            "in": "query",
            "description": "The offset from the first result to list from",
            "type": "integer",
            "default": 0,
            "minimum": 0
          }
        ],
        "responses": {
          "200": {
            "description": "A list of categories.",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Idiom"
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "idiom"
        ],
        "summary": "Create",
        "description": "Create an idiom",
        "operationId": "create",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "idiom",
            "description": "Idiom object",
            "required": true,
            "schema": {
              "items": {
                "$ref": "#/definitions/Idiom"
              }
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid params supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    },
    "/idiom/{idiomId}": {
      "get": {
        "tags": [
          "idiom"
        ],
        "summary": "Get an idiom",
        "description": "For valid response an idiom with idiomId param should be exist",
        "operationId": "getById",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "idiomId",
            "description": "Idiom id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      },
      "delete": {
        "tags": [
          "idiom"
        ],
        "summary": "Delete an idiom",
        "description": "For valid response an idiom with idiomId param should be exist",
        "operationId": "delete",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "idiomId",
            "description": "Author id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      },
      "put": {
        "tags": [
          "idiom"
        ],
        "summary": "Update",
        "description": "Update an idiom",
        "operationId": "update",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "idiom",
            "description": "Author object",
            "required": true,
            "schema": {
              "items": {
                "$ref": "#/definitions/Author"
              }
            }
          },
          {
            "in": "path",
            "name": "idiomId",
            "description": "Author id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid params supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    }   },   "definitions": {
    "Author": {
      "type": "object",
      "required": [
        "id",
        "name",
        "notes"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        }
      }
    },
    "Category": {
      "type": "object",
      "required": [
        "id",
        "description"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "description": {
          "type": "string"
        }
      }
    },
    "Idiom": {
      "type": "object",
      "required": [
        "id",
        "description"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "description": {
          "type": "string"
        }
      }
    }   } }

Мой авторский завод:

(function () {
    'use strict';

    angular
        .module('qrbweb')
        .factory('AuthorFactory', ['$http', '$q', AuthorFactory]);

    function AuthorFactory($http, $q) {

        var url = "http://localhost:3000/authors/";
        var authors = [];

        function list() {
            var d = $q.defer();
            $http.get(url).then(function (response, $q) {
                d.resolve(response);
                authors = response.data;
            });
            return d.promise;
        }

        function remove(id) {
            var d = $q.defer();
            $http.delete(url + id).then(function (response, $q) {
                d.resolve(response);
                list();
            });
            return d.promise;
        }

        function create(author) {
            var d = $q.defer();
            $http.post(url, author).then(function (response, $q) {
                d.resolve(response);
            });
            return d.promise;
        }

        function update(author) {
            var d = $q.defer();
            $http.put(url + author.id, author).then(function (response, $q) {
                d.resolve(response);
            });
            return d.promise;
        }

        function getById(id) {
            var d = $q.defer();
            $http.get(url + id).then(function (response, $q) {
                d.resolve(response);
            });
            return d.promise;
        }

        function get() {
            return authors;
        }

        return {
            list: list,
            remove: remove,
            create: create,
            get: get,
            getById: getById,
            update: update
        };
    }
})();

И, наконец, мой индекс happi:

var hapi = require('hapi');
var server = new hapi.Server();
var intert = require('inert');
var routes = require('./routes');

server.connection({port: 3000});

server.register(intert, function () {
});

server.route(routes);

server.route({
    method: 'GET',
    path: '/{path*}',
    handler: {
        directory: {
            path: 'src/client/main/',
            listing: false,
            index: true
        }
    }
});

server.route({
    method: 'GET',
    path: '/app/{param*}',
    handler: {
        directory: {
            path: 'src/client/main/app/',
            redirectToSlash: true,
            index: true
        }
    }
});

server.route({
    method: 'GET',
    path: '/bower_components/{params*}',
    handler: {
        directory: {
            path: 'bower_components/'
        }
    }
});

server.start(function () {
    console.log('Running server at ', server.info.uri);
});

Спасибо !

0

Что-то не соответствует.

Таким образом, существует несоответствие номеров портов, пути API и способа определения идентификатора. Я понятия не имею, что делают хапиджи и чванство, поэтому я проигнорирую их и позволяю вам компенсировать мое невежество :)

Попробуй это

  1. Проверьте конечную точку удаления, запустив curl -i -X DELETE localhost:8080/api/author/8 Если это работает, то работает сторона Grails.
  2. Измените конечную точку в AngularJS на $http.delete("http://localhost:8000/api/author/" + id)
  • 0
    Спасибо Эммануэль!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню