简体   繁体   English

Corda Settler UI-尝试通过API发送问题请求时出现错误404

[英]Corda Settler UI - Error 404 when trying to send an issue-obligation request via API

Basically, I have created my own settlement rail for corda-settler and now I'm trying to create an UI for demonstration. 基本上,我已经为corda-settler创建了自己的结算栏,现在我正在尝试创建一个用于演示的UI。 I'm having an issue trying to create an obligation using the API call. 我在尝试使用API​​调用创建义务时遇到问题。 I'm using the built-in jettywebserver and coded my own API using javascript to send the request. 我正在使用内置的jettywebserver,并使用javascript编写了自己的API,以发送请求。 Hope to seek some advice/insight on where I might be doing it wrong, I'm relatively new to this and not sure if the following codes provided would help you all to better advise me on this issue but please let me know if more information needs to be provided. 希望就我可能在哪里做错的问题寻求建议/见解,我对此还比较陌生,不知道所提供的以下代码是否可以帮助大家在这个问题上给我更好的建议,但是如果有更多信息,请告诉我需要提供。 Thank you in advance! 先感谢您!

This is the UI that I have created (sorry, not enough reputation to post an image directly): 这是我创建的用户界面(很抱歉,声誉不足,无法直接发布图像):

https://imgur.com/xPUQdUj https://imgur.com/xPUQdUj

and upon clicking Create Obligation button, this returns: 在单击创建义务按钮时,将返回:

https://imgur.com/3X1FPp6 https://imgur.com/3X1FPp6

It seems to me like I'm not getting/calling the API properly but I just can't figure out what went wrong because the codes seem fine to me. 在我看来,我没有正确获取/调用API,但我只是想不出出什么问题,因为代码对我来说似乎很好。

This is my index.html file: 这是我的index.html文件:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Settler CorDapp</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
          integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="css/index.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
            integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
            crossorigin="anonymous"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0-rc.1/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.2.0/ui-bootstrap-tpls.min.js"></script>

    <script src="js/main.js"></script>
    <script src="js/createObligationModal.js"></script>
    <script src="js/settleModal.js"></script>

</head>


<body ng-app="demoAppModule" ng-controller="DemoAppCtrl as demoApp">

<nav class="navbar navbar-default">
    <div class="container-fluid">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">{{demoApp.thisNode}}</a>
        </div>
        <button ng-click="demoApp.openCreateObligationModal()" type="button" class="btn btn-primary navbar-btn">Create Obligation</button>
        <button ng-click="demoApp.refresh()" type="button" class="btn btn-default navbar-btn"><span
                class="glyphicon glyphicon-refresh"></span></button>
    </div>
</nav>

<script type="text/ng-template" id="createObligationModal.html">
    <div class="modal-header">
        <h4 class="modal-title">Add new Obligation</h4>
    </div>

    <form>
        <div class="modal-body">
            <div class="form-group">
                <label for="createObligationCounterparty" class="control-label">Counter-party:</label>
                <select ng-model="createObligationModal.form.counterparty" class="form-control" id="createObligationCounterparty"
                        ng-options="peer as peer for peer in createObligationModal.peers">
                </select>
            </div>
            <div class="form-group">
                <label for="createObligationCurrency" class="control-label">Currency (ISO code):</label>
                <input type="text" ng-model="createObligationModal.form.currency" class="form-control" id="createObligationCurrency">
            </div>
            <div class="form-group">
                <label for="createObligationAmount" class="control-label">Amount (Int):</label>
                <input type="text" ng-model="createObligationModal.form.amount" class="form-control" id="createObligationAmount">
            </div>
            <div class="form-group">
                <label for="createObligationDueDate" class="control-label">Due Date:</label>
                <input type="date" ng-model="createObligationModal.form.duedate" class="form-control" id="createObligationDueDate" min="2020-01-01" max="2022-12-31">
            </div>


            <div ng-show="createObligationModal.formError" class="form-group">
                <div class="alert alert-danger" role="alert">
                    <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
                    <span class="sr-only">Error:</span>
                    Enter valid Obligation creation parameters
                </div>
            </div>
        </div>
        <div class="modal-footer">
            <button ng-click="createObligationModal.cancel()" type="button" class="btn btn-default">Close</button>
            <button ng-click="createObligationModal.create()" type="button" class="btn btn-primary">Create Obligation</button>
        </div>
    </form>
</script>

<script type="text/ng-template" id="createObligationMsgModal.html">
    <div class="modal-body" id="create-Obligation-modal-body">
        {{ createObligationMsgModal.message }}
    </div>
</script>

<script type="text/ng-template" id="settleModal.html">
    <div class="modal-header">
        <h4 class="modal-title">Settle Obligation</h4>
    </div>
    <form>
        <div class="modal-body">
            <div class="form-group">
                <label for="settleCurrency" class="control-label">Currency (ISO code):</label>
                <input type="text" ng-model="settleModal.form.currency" class="form-control" id="settleCurrency">
            </div>
            <div class="form-group">
                <label for="settleAmount" class="control-label">Amount (Int):</label>
                <input type="text" ng-model="settleModal.form.amount" class="form-control" id="settleAmount">
            </div>
            <div ng-show="settleModal.formError" class="form-group">
                <div class="alert alert-danger" role="alert">
                    <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
                    <span class="sr-only">Error:</span>
                    Enter valid Obligation settle parameters.
                </div>
            </div>
        </div>
        <div class="modal-footer">
            <button ng-click="settleModal.cancel()" type="button" class="btn btn-default">Close</button>
            <button ng-click="settleModal.settle()" type="button" class="btn btn-primary">Settle</button>
        </div>
    </form>
</script>

<script type="text/ng-template" id="settleMsgModal.html">
    <div class="modal-body" id="settle-modal-body">
        {{ settleMsgModal.message }}
    </div>
</script>

<div class="row">
    <div class="col-md-1"></div>
    <div class="col-md-10">
        <div ng-show="!demoApp.obligations.length" class="panel panel-primary">
            <div class="panel-heading">
                <h3 class="panel-title">There are no recorded Obligations</h3>
            </div>
            <div class="panel-body">Use the "Create Obligation" button to send an Obligation to a peer.</div>
        </div>

        <div ng-show="demoApp.obligations.length" class="panel panel-primary">
            <div class="panel-heading">
                <h3 class="panel-title">Recorded Obligations:</h3>
            </div>

            <div class="panel-body">
                <table class="table">
                    <thead>
                    <tr>
                        <th>From</th>
                        <th>To</th>
                        <th>Amount</th>
                        <th>Paid</th>
                        <th>Actions</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr ng-repeat="obligation in demoApp.obligations">
                        <td class="vert-align">{{obligation.obligee.substring(0,30)}}</td>
                        <td class="vert-align">{{obligation.obligor.substring(0,30)}}</td>
                        <td class="vert-align">{{obligation.faceAmount}}</td>
                        <td class="vert-align">{{obligation.amountPaid}}</td>
                        <td>
                            <div class="btn-group" role="group">
                                <button ng-click="demoApp.openSettleModal(obligation.linearId.id)" type="button" class="btn btn-primary">Settle
                                </button>
                            </div>
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>

        </div>
        <div class="col-md-1"></div>
    </div>
</div>

</body>

</html>

Here's my ObligationPlugin.kt and ObligationApi.kt files, respectively: package com.r3.corda.finance.obligation 这分别是我的ObligationPlugin.ktObligationApi.kt文件:包com.r3.corda.finance.obligation

import net.corda.core.messaging.CordaRPCOps
import net.corda.webserver.services.WebServerPluginRegistry
import java.util.function.Function

class ObligationPlugin : WebServerPluginRegistry {
    override val webApis: List<Function<CordaRPCOps, out Any>> = listOf(Function(::ObligationApi))
    override val staticServeDirs: Map<String, String> = mapOf(
            "obligation" to javaClass.classLoader.getResource("settlerWeb").toExternalForm()
    )
}

package com.r3.corda.finance.obligation

import com.r3.corda.finance.obligation.flows.CreateObligation
import com.r3.corda.finance.obligation.states.Obligation
import net.corda.core.contracts.Amount
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.getOrThrow
import java.util.*
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response

@Path("obligation")
class ObligationApi(val rpcOps: CordaRPCOps) {

    private val myIdentity = rpcOps.nodeInfo().legalIdentities.first()

    @GET
    @Path("me")
    @Produces(MediaType.APPLICATION_JSON)
    fun me() = mapOf("me" to myIdentity)

    @GET
    @Path("peers")
    @Produces(MediaType.APPLICATION_JSON)
    fun peers() = mapOf("peers" to rpcOps.networkMapSnapshot()
            .filter { nodeInfo -> nodeInfo.legalIdentities.first() != myIdentity }
            .map { it.legalIdentities.first().name.organisation })

    @GET
    @Path("issue-obligation")
    fun issueObligation(@QueryParam(value = "party") party: String,
                        @QueryParam(value = "currency") currency: String,
                        @QueryParam(value = "amount") amount: Int,
                        @QueryParam(value = "duedate") duedate: Date
    ): Response {
        // 1. Get party objects for the counterparty.
        val obligorIdentity = rpcOps.partiesFromName(party, exactMatch = false).singleOrNull()
                ?: throw IllegalStateException("Couldn't lookup node identity for $party.")
        // 2. Create an amount object.
        val issueAmount = Amount(amount.toLong() * 100, Currency.getInstance(currency))
        // 3. Convert duedate to unix timestamp (in seconds)
        val unixTime = (duedate.time) / 1000
        // 4. Retrieve obligee identity
//        val obligeeIdentity = myIdentity

        // 5. Start the IssueObligation flow. We block and wait for the flow to return.
        val (status, message) = try {
            val flowHandle = rpcOps.startFlowDynamic(
                    CreateObligation.Initiator::class.java,
                    issueAmount,
                    CreateObligation.InitiatorRole.OBLIGEE,
                    obligorIdentity,
                    unixTime,
                    true
            )

            val result = flowHandle.returnValue.getOrThrow()
            flowHandle.close()
            Response.Status.CREATED to "Transaction id ${result.id} committed to ledger.\n${result.outputs}"
        } catch (e: Exception) {
            Response.Status.BAD_REQUEST to e.message
        }

        // 4. Return the result.
        return Response.status(status).entity(message).build()
    }

    @GET
    @Path("obligations")
    @Produces(MediaType.APPLICATION_JSON)
    fun obligations(): List<Obligation<*>> {
        val statesAndRefs = rpcOps.vaultQuery(Obligation::class.java).states
        return statesAndRefs
                .map { stateAndRef -> stateAndRef.state.data }
                .map { state ->
                    // We map the anonymous lender and borrower to well-known identities if possible.
                    val possiblyWellKnownLender = rpcOps.wellKnownPartyFromAnonymous(state.obligee) ?: state.obligee
                    val possiblyWellKnownBorrower = rpcOps.wellKnownPartyFromAnonymous(state.obligor) ?: state.obligor

                    Obligation(state.faceAmount,
                            possiblyWellKnownBorrower,
                            possiblyWellKnownLender,
                            state.dueBy,
                            state.createdAt,
                            state.settlementMethod,
                            state.payments,
                            state.linearId)
                }
    }
}

and the followings are main.js and createObligationModal.js files, respectively: 以下分别是main.jscreateObligationModal.js文件:

"use strict";

// Define your backend here.
angular.module('demoAppModule', ['ui.bootstrap']).controller('DemoAppCtrl', function ($http, $location, $uibModal) {
    const demoApp = this;

    const apiBaseURL = "/api/obligation/";

    // Retrieves the identity of this and other nodes.
    let peers = [];
    $http.get(apiBaseURL + "me").then((response) => demoApp.thisNode = response.data.me);
    $http.get(apiBaseURL + "peers").then((response) => peers = response.data.peers);

    /** Displays the obligation creation modal. */
    demoApp.openCreateObligationModal = () => {
        const createObligationModal = $uibModal.open({
            templateUrl: 'createObligationModal.html',
            controller: 'CreateObligationModalCtrl',
            controllerAs: 'createObligationModal',
            resolve: {
                demoApp: () => demoApp,
                apiBaseURL: () => apiBaseURL,
                peers: () => peers,
                refreshCallback: () => demoApp.refresh
            }
        });

        // Ignores the modal result events.
        createObligationModal.result.then(() => {
        }, () => {
        });
    };

    /** Displays the Obligation settlement modal. */
    demoApp.openSettleModal = (id) => {
        const settleModal = $uibModal.open({
            templateUrl: 'settleModal.html',
            controller: 'SettleModalCtrl',
            controllerAs: 'settleModal',
            resolve: {
                demoApp: () => demoApp,
                apiBaseURL: () => apiBaseURL,
                id: () => id,
                refreshCallback: () => demoApp.refresh
            }
        });

        settleModal.result.then(() => {
        }, () => {
        });
    };

    /** Refreshes the front-end. */
    demoApp.refresh = () => {
        // Update the list of Obligations.
        $http.get(apiBaseURL + "obligations").then((response) => demoApp.obligations =
            Object.keys(response.data).map((key) => response.data[key]));
    }

    demoApp.refresh();
});

// Causes the webapp to ignore unhandled modal dismissals.
angular.module('demoAppModule').config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);

"use strict";

angular.module('demoAppModule').controller('CreateObligationModalCtrl', function ($http, $uibModalInstance, $uibModal, apiBaseURL, peers, refreshCallback) {
    const createObligationModal = this;

    createObligationModal.peers = peers;
    createObligationModal.form = {};
    createObligationModal.formError = false;

    /** Validate and create an Obligation. */
    createObligationModal.create = () => {
        if (invalidFormInput()) {
            createObligationModal.formError = true;
        } else {
            createObligationModal.formError = false;

            const party = createObligationModal.form.counterparty;
            const currency = createObligationModal.form.currency;
            const amount = createObligationModal.form.amount;
            const duedate = createObligationModal.form.duedate;

            $uibModalInstance.close();

            // We define the Obligation creation endpoint.
            const issueObligationEndpoint =
                apiBaseURL +
                `issue-obligation?party=${party}&currency=${currency}&amount=${amount}&duedate=${duedate}`;

            // We hit the endpoint to create the Obligation and handle success/failure responses.
            $http.get(issueObligationEndpoint).then(
                (result) => {
                    createObligationModal.displayMessage(result);
                    refreshCallback();
                },
                (result) => {
                    createObligationModal.displayMessage(result);
                    refreshCallback();
                }
            );
        }
    };

    /** Displays the success/failure response from attempting to create an Obligation. */
    createObligationModal.displayMessage = (message) => {
        const createObligationMsgModal = $uibModal.open({
            templateUrl: 'createObligationMsgModal.html',
            controller: 'createObligationMsgModalCtrl',
            controllerAs: 'createObligationMsgModal',
            resolve: {
                message: () => message
            }
        });

        // No behaviour on close / dismiss.
        createObligationMsgModal.result.then(() => {}, () => {});
    };

    /** Closes the Obligation creation modal. */
    createObligationModal.cancel = () => $uibModalInstance.dismiss();

    // Validates the Obligation.
    function invalidFormInput() {
        return isNaN(createObligationModal.form.amount) || (createObligationModal.form.counterparty === undefined);
    }
});

// Controller for the success/fail modal.
angular.module('demoAppModule').controller('createObligationMsgModalCtrl', function ($uibModalInstance, message) {
    const createObligationMsgModal = this;
    createObligationMsgModal.message = message.data;
});

continue... 继续...

Below is a snippet of the web logs generated on PartyA node: 以下是在PartyA节点上生成的Web日志的摘要:

[INFO ] 2019-07-11T07:08:01,782Z [main] server.AbstractConnector.doStart - Started ServerConnector@179af25f{HTTP/1.1,[http/1.1]}{0.0.0.0:10007} {}
[INFO ] 2019-07-11T07:08:01,782Z [main] server.Server.doStart - Started @77789ms {}
[INFO ] 2019-07-11T07:08:01,782Z [main] internal.NodeWebServer.initWebServer - Starting webserver on address localhost:10007 {}
[WARN ] 2019-07-11T07:14:55,332Z [qtp1745174877-127] server.HttpChannel.handleException - /api/obligation/issue-obligation {}
javax.servlet.ServletException: javax.servlet.ServletException: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.r3.corda.finance.obligation.ObligationApi.issueObligation, parameter party
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.Server.handle(Server.java:561) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:334) [jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251) [jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279) [jetty-io-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:104) [jetty-io-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124) [jetty-io-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:243) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:679) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:597) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_212]
Caused by: javax.servlet.ServletException: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.r3.corda.finance.obligation.ObligationApi.issueObligation, parameter party
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    ... 14 more
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.r3.corda.finance.obligation.ObligationApi.issueObligation, parameter party
    at com.r3.corda.finance.obligation.ObligationApi.issueObligation(ObligationApi.kt) ~[cordapp-contracts-states-0.1.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_212]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_212]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_212]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_212]
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    ... 14 more
[WARN ] 2019-07-11T07:18:53,277Z [qtp1745174877-127] server.HttpChannel.handleException - /api/obligation/issue-obligation {}
javax.servlet.ServletException: javax.servlet.ServletException: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.r3.corda.finance.obligation.ObligationApi.issueObligation, parameter party
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.Server.handle(Server.java:561) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:334) [jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251) [jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279) [jetty-io-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:104) [jetty-io-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124) [jetty-io-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:243) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:679) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:597) [jetty-util-9.4.7.v20170914.jar:9.4.7.v20170914]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_212]
Caused by: javax.servlet.ServletException: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.r3.corda.finance.obligation.ObligationApi.issueObligation, parameter party
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    ... 14 more
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.r3.corda.finance.obligation.ObligationApi.issueObligation, parameter party
    at com.r3.corda.finance.obligation.ObligationApi.issueObligation(ObligationApi.kt) ~[cordapp-contracts-states-0.1.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_212]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_212]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_212]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_212]
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) ~[jersey-common-2.25.jar:?]
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) ~[jersey-server-2.25.jar:?]
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) ~[jersey-container-servlet-core-2.25.jar:?]
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) ~[jetty-servlet-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126) ~[jetty-server-9.4.7.v20170914.jar:9.4.7.v20170914]
    ... 14 more

And the Obligation data class: 和义务数据类:

package com.r3.corda.finance.obligation.states

import com.r3.corda.finance.obligation.types.Money
import com.r3.corda.finance.obligation.types.Payment
import com.r3.corda.finance.obligation.types.PaymentStatus
import com.r3.corda.finance.obligation.types.SettlementMethod
import net.corda.core.contracts.Amount
import net.corda.core.contracts.LinearState
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.crypto.toStringShort
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.serialization.CordaSerializable
import java.time.Instant

/**
 * Obligation Settlement Assumptions:
 *
 * 1. Obligation are just for fiat currency and digital currency for the time being. Support for arbitrary token states
 *    can be added later e.g. shares.
 * 2. Obligations are given a face value in some currency or digital currency e.g. BTC or GBP.
 * 3. Obligations can be settled in a currency or digital currency other than the one specified for the face value.
 *    - If a different currency is used to the face value currency, then a conversion is done for the time the
 *      obligation was first raised.
 *    - This process requires a novation of the obligation from one currency to another.
 * 4. Obligations can be paid down with multiple payments.
 * 5. Obligations can only be paid down with one currency or digital currency type.
 *    - For example, if one currency is initially used, it must be used for the remainder of the payments.
 * 6. The obligee specifies which token states are acceptable for payment on ledger and which settlement rails are
 *    appropriate for off-ledger.
 *    - Only one settlement method can be supplied at any one time.
 * 7. Obligations are considered settled when the sum of all payments in the face value currency equal the face value.
 * 8. Obligations are considered in default if they are not fully paid by the dueDate, if one is specified.
 *
 */
data class Obligation<T : Money>(
        /** Obligations are always denominated in some token type as we need a reference for FX purposes. */
        val faceAmount: Amount<T>,
        /** The payer. Can be pseudo-anonymous. */
        val obligor: AbstractParty,
        /** The beneficiary. Can be pseudo-anonymous. */
        val obligee: AbstractParty,
        /** When the obligation should be paid by. May not always be required. */
        val dueBy: Instant? = null,
        /** The time when the obligation was created. */
        val createdAt: Instant = Instant.now(),
        /** Settlement methods the obligee will accept: On ledger, off ledger (crypto, swift, PISP, paypal, etc.). */
        val settlementMethod: SettlementMethod? = null,
        /** The obligation can be paid in parts. This lists all payments in respect of this obligation */
        val payments: List<Payment<out Money>> = emptyList(),
        /** Unique identifier for the obligation. */
        override val linearId: UniqueIdentifier = UniqueIdentifier()
) : LinearState {

    @CordaSerializable
    enum class SettlementStatus { UNSETTLED, SETTLED, PARTIALLY_SETTLED }

    /** Always returns the obligor and obligee. */
    override val participants: List<AbstractParty> get() = listOf(obligee, obligor)

    /** The sum of amounts for all payments. */
    val amountPaid: Amount<T>
        get() = payments
                .filter { it.status == PaymentStatus.SETTLED }
                .map { it.amount }
                .fold(Amount.zero(faceAmount.token)) { acc, amount -> acc + amount as Amount<T> }

    /** A defaulted obligation is one where the current time is greater than the [dueBy] time. */
    val inDefault: Boolean get() = dueBy?.let { Instant.now() > dueBy } ?: false

    /** Returns the current state of the obligation. */
    val settlementStatus: SettlementStatus
        get() {
            return when {
                payments.isEmpty() -> SettlementStatus.UNSETTLED
                payments.isNotEmpty() && amountPaid < faceAmount -> SettlementStatus.PARTIALLY_SETTLED
                payments.isNotEmpty() && amountPaid == faceAmount -> SettlementStatus.SETTLED
                else -> throw IllegalStateException("Shouldn't reach here.")
            }
        }

    /** For adding or changing the settlement method. */
    fun withSettlementMethod(settlementMethod: SettlementMethod?): Obligation<T> {
        return if (settlementStatus != SettlementStatus.UNSETTLED) {
            throw IllegalStateException("Cannot change settlement method after a payment has been made.")
        } else copy(settlementMethod = settlementMethod)
    }

    /** Update the due by date. */
    fun withDueByDate(dueBy: Instant) = copy(dueBy = dueBy)

    /** Update the due by date. */
    fun withNewCounterparty(oldParty: AbstractParty, newParty: AbstractParty): Obligation<T> {
        return when {
            obligee == oldParty -> copy(obligee = newParty)
            obligor == oldParty -> copy(obligor = newParty)
            else -> throw IllegalArgumentException("The oldParty is not recognised as a participant in this obligation.")
        }
    }

    fun <U : Money> withNewFaceValueToken(newAmount: Amount<U>): Obligation<U> {
        return if (payments.isEmpty()) {
            Obligation(newAmount, obligor, obligee, dueBy, createdAt, settlementMethod, emptyList(), linearId)
        } else {
            throw IllegalStateException("The faceValue token type cannot be updated after payments have been made.")
        }
    }

    /** Update the amount, keeping the token type the same. */
    fun withNewFaceValueQuantity(newAmount: Amount<T>): Obligation<T> {
        return if (newAmount < amountPaid) {
            throw IllegalStateException("Can't reduce the faceAmount to less than the current amountPaid.")
        } else copy(faceAmount = newAmount)
    }

    /** Add a new payment to the payments list. */
    fun withPayment(payment: Payment<T>): Obligation<T> {
        val newAmountPaid = amountPaid + payment.amount
        return if (newAmountPaid > faceAmount) {
            throw IllegalStateException("You cannot over pay an obligation.")
        } else {
            copy(payments = payments + payment)
        }
    }

    private fun resolveParty(resolver: (AbstractParty) -> Party, abstractParty: AbstractParty): Party {
        return abstractParty as? Party ?: resolver(abstractParty)
    }

    /** Returns the obligation with well known identities. */
    fun withWellKnownIdentities(resolver: (AbstractParty) -> Party): Obligation<T> {
        return copy(obligee = resolveParty(resolver, obligee), obligor = resolveParty(resolver, obligor))
    }

    override fun toString(): String {
        val obligeeString = (obligee as? Party)?.name?.organisation
                ?: obligee.owningKey.toStringShort().substring(0, 10)
        val obligorString = (obligor as? Party)?.name?.organisation
                ?: obligor.owningKey.toStringShort().substring(0, 10)
        val settlementMethod = if (settlementMethod == null) "No settlement method added" else settlementMethod.toString()
        var paymentString = ""
        if (payments.isNotEmpty()) {
            payments.forEach { paymentString += "\n\t\t\t$it" }
        } else {
            paymentString = "\n\t\t\tNo payments made."
        }
        return "Obligation($linearId): $obligorString owes $obligeeString $faceAmount ($amountPaid paid)." +
                "\n\t\tSettlement status: $settlementStatus" +
                "\n\t\tSettlementMethod: $settlementMethod" +
                "\n\t\tPayments:" +
                paymentString
    }

}

Creating obligation, updating settlement method and settling an obligation off ledger flows are all running fine on the terminal. 在终端上,创建义务,更新结算方法以及从分类账流中结算义务都可以正常运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 尝试发送POST请求时收到404错误 - receiveing 404 error when trying to send a POST request 尝试通过角度服务通过服务发送请求时,错误请求404 - Bad request 404 when trying to POST request via service in angular 尝试将记录发送到数据库时出现 404 错误 - 404 error when trying to send records to a database 向 API 执行“获取”请求时出现 404 错误 - 404 error when performing "Get" request to API 尝试发布到 api 路由时出现 404 错误 - 404 error when trying to post to api route 尝试对 Hubspot 表单 next.js 应用程序发出 api POST 请求时出现 404 错误 - Getting a 404 ERROR when trying to make api POST request for a Hubspot form next.js app 尝试从Google Map API获取照片时出现404错误 - 404 Error when trying to get the photos from Google Map API 当尝试通过request.post发送追加附件时,表单数据库抛出无法读取null错误的属性 - form-data library throwing cannot read property of null error when trying append attachments to send via request.post 尝试访问API调用时出现Javascript 404错误 - Javascript 404 error when trying to access API call POST 请求正在使用 POSTMAN,但是当我尝试使用 Axios 从浏览器(UI)调用相同的链接时,它显示 404 错误 | node.js - POST request is working using POSTMAN, but when I'm trying to call the same link using Axios from browser(UI) it's showing 404 error | node.js
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM