Skip to content

[FEATURE] Implement URL query string parsing in REST API server #33

Description

@chizy7

Description

The RestAPIServer::parseQueryString() method is currently a stub that returns an empty parameters map, preventing REST API endpoints from processing URL query parameters for filtering, pagination, and time range selection.

Current Behavior

std::unordered_map<std::string, std::string>
RestAPIServer::parseQueryString(const std::string& query) {
  std::unordered_map<std::string, std::string> params;
  // Simple query string parsing (not implemented for brevity)
  boost::ignore_unused(query);
  return params;
}

Located at: visualization/WebServer.cpp:1000-1006

Impact

  • REST API cannot process query parameters from URLs
  • No support for time range filtering (e.g., ?start=123&end=456)
  • No pagination support (e.g., ?limit=100&offset=0)
  • No metric filtering (e.g., ?metrics=pnl,sharpe_ratio)
  • Limits API flexibility and usability

Expected Behavior

Parse standard URL query strings and return key-value pairs:

Examples:

  • Input: "start=1234567890&end=9876543210&limit=100"
  • Output: {{"start", "1234567890"}, {"end", "9876543210"}, {"limit", "100"}}
  • Input: "symbol=BTC-USD&interval=1h"
  • Output: {{"symbol", "BTC-USD"}, {"interval", "1h"}}
  • Input: "" (empty or malformed)
  • Output: {} (empty map, graceful degradation)

Implementation Requirements

  1. Parse query string format:
  • Split by & delimiter for parameters
  • Split by = for key-value pairs
  • Handle empty/missing values gracefully
  1. URL decoding:
  • Decode percent-encoded characters (e.g., %20 → space)
  • Handle special characters properly
  • Support UTF-8 encoding
  1. Error handling:
  • Return empty map for null/empty input
  • Skip malformed parameters
  • No exceptions thrown (graceful degradation)
  1. Edge cases:
  • Handle parameters without values: key= → {{"key", ""}}
  • Handle duplicate keys (keep last value or create array)
  • Handle ? prefix if present in query string

Implementation Approach I am Thinking of and Considering Tradeoffs

Option 1: Manual parsing (lightweight)

std::unordered_map<std::string, std::string>
RestAPIServer::parseQueryString(const std::string& query) {
  std::unordered_map<std::string, std::string> params;

  if (query.empty()) return params;

  std::istringstream iss(query);
  std::string pair;

  while (std::getline(iss, pair, '&')) {
    auto eqPos = pair.find('=');
    if (eqPos != std::string::npos) {
      std::string key = pair.substr(0, eqPos);
      std::string value = pair.substr(eqPos + 1);
      params[urlDecode(key)] = urlDecode(value);
    }
  }

  return params;
}

Option 2: Using Boost

  • I can leverage existing Boost dependency
  • Use boost::algorithm::split for parsing
  • More robust handling

Additional helper needed:

std::string RestAPIServer::urlDecode(const std::string& str);

For decoding percent-encoded characters.

Affected API Endpoints

  • GET /api/v1/strategies/{id}/performance?start=X&end=Y
  • GET /api/v1/strategies/{id}/chart?metric=pnl&range=1h
  • Any future endpoints requiring query parameters

Testing Considerations

  • Test with various query string formats
  • Test URL encoding/decoding
  • Test empty and malformed inputs
  • Test with special characters
  • Verify no crashes on edge cases

Priority

Medium - Needed for full REST API functionality, but endpoints work without it (just with default parameters)

For easy access of the implementation check

  • visualization/WebServer.cpp (implement parseQueryString() and add urlDecode() helper)
  • visualization/WebServer.h (add urlDecode() method declaration if needed)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions