You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nim Prologue函数数据传递异常:后端接收前端提交数据为空

后端无法获取Fetch提交的表单参数问题

问题描述

我编写了HTML和JS前端代码,通过fetch接口/sona-master/availability-json提交表单数据,但基于Nim Prologue实现的后端checkRoom函数无法获取提交的参数,接收值为空。附上前后端代码及仓库地址,请求协助排查解决。

前端代码

<div class="col-lg-4">
    <div class="room-booking">
        <h3>Your Reservation</h3>
        <form id="f2" method="post" action="" class="needs-validation">
            <input type="hidden" name="room_id" value="1">
            <div class="check-date">
                <label for="date-in">Check In:</label>
                <input type="text" class="date-input" name="start" id="date-in" autocomplete="off">
                <i class="icon_calendar"></i>
            </div>
            <div class="check-date">
                <label for="date-out">Check Out:</label>
                <input type="text" class="date-input" id="date-out" name="end" autocomplete="off">
                <i class="icon_calendar"></i>
            </div>
            <div class="select-option">
                <label for="guest">Guests:</label>
                <select id="guest">
                    <option value="">3 Adults</option>
                </select>
            </div>
            <div class="select-option">
                <label for="room">Room:</label>
                <select id="room">
                    <option value="">1 Room</option>
                </select>
            </div>
            <button type="submit" id="b2">Check Availability</button>
        </form>
    </div>
</div>
</div>
</div>
</section>
<!-- Room Details Section End -->

<script>
    const dateIn = document.getElementById('date-in');
    const dateOut = document.getElementById('date-out');
    
    if (dateIn !== null && dateOut !== null) {
        document.getElementById('b2').onclick = function(event){
            event.preventDefault();
            console.log('clicked');

            let form = document.getElementById('f2');
            let formData = new FormData(form);
            formData.append("room_id", "1")

            fetch('/sona-master/availability-json', {
                method: 'post',
                body: formData,
            })
                .then(response => response.json())
                .then(data => {
                    if (data.ok) {
                        Notiflix.Notify.success('<p>Room is available</p>' + '<p><a href="#!" class="btn btn-primary">' + 'Book Now</a></p>')
                    } else {
                        Notiflix.Notify.failure('Room is not available')
                    }
                })
        };
    }
</script>

后端代码(Nim)

import prologue, json
import times
import asyncdispatch
import strutils

import ../views/[index, layout, choose_room]
import ../database/roomrestrictions
import ../models/models

proc checkRoom*(ctx: Context) {.async.} =
  
  var sd = ctx.getFormParams("start")
  var
    ed = ctx.getPostParams("end")
  var

    startDate = parse(sd, "d MMMM, yyyy")
  var
    endDate = parse(ed, "d MMMM, yyyy")
    roomi = ctx.getPostParams("room_id")
  var

    roomID = parseInt(roomi)
    # roomID = parseInt(room_id)
  echo roomID
  var

    db = newDatabase3()

    available = db.searchAvailabilityByDatesByRoomID(startDate, endDate, roomID)

    a = %*
      {"ok": available, "message": "", "roomID": $roomID, "startDate": sd, "endDate": ed}

  resp jsonResponse(a)

仓库地址

GitLab仓库:https://gitlab.com/a60030/aa


排查与解决方案

核心问题分析

  1. Prologue未启用Multipart解析:前端用FormData提交数据时,请求头Content-Type为multipart/form-data,而Prologue默认未开启该类型的解析支持,导致后端无法读取参数。
  2. 参数获取方法混用:后端同时使用getFormParams和getPostParams,getFormParams通常用于解析URL查询参数,而非POST表单数据,应该统一使用getPostParams。
  3. 路由路径不匹配:前端请求路径是/sona-master/availability-json,需确认后端路由是否绑定了该完整路径,若后端仅绑定/availability-json,则路径不匹配导致参数无法接收。
  4. 参数未做空值处理:直接对空字符串调用parse会报错,需先判断参数是否为空。

具体修复步骤

1. 后端启用Multipart解析

在Prologue应用初始化时添加enableMultipart = true,确保能解析FormData:

let app = newApp(settings = newSettings(enableMultipart = true))

2. 统一使用getPostParams获取参数

修改后端checkRoom函数,全部用getPostParams获取POST参数,并添加空值判断:

proc checkRoom*(ctx: Context) {.async.} =
  var sd = ctx.getPostParams("start", default = "")
  var ed = ctx.getPostParams("end", default = "")
  var roomi = ctx.getPostParams("room_id", default = "")

  if sd.len == 0 or ed.len == 0 or roomi.len == 0:
    resp jsonResponse(%*{"ok": false, "message": "Missing required parameters"})
    return

  let startDate = parse(sd, "d MMMM, yyyy")
  let endDate = parse(ed, "d MMMM, yyyy")
  let roomID = parseInt(roomi)

  echo roomID
  let db = newDatabase3()
  let available = db.searchAvailabilityByDatesByRoomID(startDate, endDate, roomID)

  let a = %*
    {"ok": available, "message": "", "roomID": $roomID, "startDate": sd, "endDate": ed}

  resp jsonResponse(a)

3. 确认路由路径匹配

检查后端路由注册代码,确保路径与前端请求一致:

app.post("/sona-master/availability-json", checkRoom)

如果后端没有/sona-master前缀,需修改前端fetch的URL为/availability-json。

4. 前端优化(可选)

给select标签添加name属性,确保这些参数能被FormData收集:

<select id="guest" name="guest">
    <option value="">3 Adults</option>
</select>
<select id="room" name="room">
    <option value="">1 Room</option>
</select>

内容的提问来源于stack exchange,提问作者me0045

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 02:00:56