/* ****************************************************************************
*
* restService - 
*/
std::string restService(ConnectionInfo* ciP, RestService* serviceV)
{
  std::vector<std::string>  compV;
  int                       components;
  JsonRequest*              jsonReqP   = NULL;
  ParseData                 parseData;
  JsonDelayedRelease        jsonRelease;

  if ((ciP->url.length() == 0) || ((ciP->url.length() == 1) && (ciP->url.c_str()[0] == '/')))
  {
    OrionError  error(SccBadRequest, "The Orion Context Broker is a REST service, not a 'web page'");
    std::string response = error.render(ciP, "");

    alarmMgr.badInput(clientIp, "The Orion Context Broker is a REST service, not a 'web page'");
    restReply(ciP, response);

    return std::string("Empty URL");
  }

  ciP->httpStatusCode = SccOk;

  components = stringSplit(ciP->url, '/', compV);

  for (unsigned int ix = 0; serviceV[ix].treat != NULL; ++ix)
  {
    if ((serviceV[ix].components != 0) && (serviceV[ix].components != components))
    {
      continue;
    }

    if ((ciP->method != serviceV[ix].verb) && (serviceV[ix].verb != "*"))
    {
      continue;
    }

    strncpy(ciP->payloadWord, serviceV[ix].payloadWord.c_str(), sizeof(ciP->payloadWord));
    bool match = true;
    for (int compNo = 0; compNo < components; ++compNo)
    {
      if (serviceV[ix].compV[compNo] == "*")
      {
        continue;
      }

      if (strcasecmp(serviceV[ix].compV[compNo].c_str(), compV[compNo].c_str()) != 0)
      {
        match = false;
        break;
      }
    }

    if (match == false)
    {
      continue;
    }

    if ((ciP->payload != NULL) && (ciP->payloadSize != 0) && (ciP->payload[0] != 0) && (serviceV[ix].verb != "*"))
    {
      std::string response;

      LM_T(LmtParsedPayload, ("Parsing payload for URL '%s', method '%s', service vector index: %d", ciP->url.c_str(), ciP->method.c_str(), ix));
      ciP->parseDataP = &parseData;
      LM_T(LmtPayload, ("Parsing payload '%s'", ciP->payload));
      response = payloadParse(ciP, &parseData, &serviceV[ix], &jsonReqP, &jsonRelease, compV);
      LM_T(LmtParsedPayload, ("payloadParse returns '%s'", response.c_str()));

      if (response != "OK")
      {
        alarmMgr.badInput(clientIp, response);
        restReply(ciP, response);

        if (jsonReqP != NULL)
        {
          jsonReqP->release(&parseData);
        }

        if (ciP->apiVersion == "v2")
        {
          delayedRelease(&jsonRelease);
        }

        compV.clear();
        return response;
      }
    }

    LM_T(LmtService, ("Treating service %s %s", serviceV[ix].verb.c_str(), ciP->url.c_str())); // Sacred - used in 'heavyTest'
    if (ciP->payloadSize == 0)
    {
      ciP->inFormat = NOFORMAT;
    }
    statisticsUpdate(serviceV[ix].request, ciP->inFormat);

    // Tenant to connectionInfo
    ciP->tenant = ciP->tenantFromHttpHeader;
    lmTransactionSetService(ciP->tenant.c_str());

    //
    // A tenant string must not be longer than 50 characters and may only contain
    // underscores and alphanumeric characters.
    //
    std::string result;
    if ((ciP->tenant != "") && ((result = tenantCheck(ciP->tenant)) != "OK"))
    {
      OrionError  error(SccBadRequest, result);

      std::string  response = error.render(ciP, "");

      alarmMgr.badInput(clientIp, result);

      if (ciP->apiVersion != "v1")
      {
        ciP->httpStatusCode = SccBadRequest;  // FIXME P9:  OK for all versions?
      }

      restReply(ciP, response);

      if (jsonReqP != NULL)
      {
        jsonReqP->release(&parseData);
      }

      if (ciP->apiVersion == "v2")
      {
        delayedRelease(&jsonRelease);
      }

      compV.clear();
        
      return response;
    }

    LM_T(LmtTenant, ("tenant: '%s'", ciP->tenant.c_str()));
    commonFilters(ciP, &parseData, &serviceV[ix]);
    scopeFilter(ciP, &parseData, &serviceV[ix]);


    //
    // If we have gotten this far the Input is OK.
    // Except for all the badVerb/badRequest, etc.
    // A common factor for all these 'services' is that the verb is '*'
    //
    // So, the 'Bad Input' alarm is cleared for this client.
    //
    if (serviceV[ix].verb != "*")
    {
      alarmMgr.badInputReset(clientIp);
    }

    std::string response = serviceV[ix].treat(ciP, components, compV, &parseData);

    filterRelease(&parseData, serviceV[ix].request);   

    if (jsonReqP != NULL)
    {
      jsonReqP->release(&parseData);
    }

    if (ciP->apiVersion == "v2")
    {
      delayedRelease(&jsonRelease);
    }

    compV.clear();

    if (response == "DIE")
    {
      orionExitFunction(0, "Received a 'DIE' request on REST interface");
    }

    restReply(ciP, response);
    return response;
  }

  std::string details = std::string("service '") + ciP->url + "' not recognized";
  alarmMgr.badInput(clientIp, details);

  ciP->httpStatusCode = SccBadRequest;
  std::string answer = restErrorReplyGet(ciP, "", ciP->payloadWord, SccBadRequest, std::string("unrecognized request"));
  restReply(ciP, answer);

  compV.clear();
  return answer;
}
Exemple #2
0
/* ****************************************************************************
*
* restService -
*/
std::string restService(ConnectionInfo* ciP, RestService* serviceV)
{
    std::vector<std::string>  compV;
    int                       components;
    XmlRequest*               reqP       = NULL;
    JsonRequest*              jsonReqP   = NULL;
    ParseData                 parseData;

    if ((ciP->url.length() == 0) || ((ciP->url.length() == 1) && (ciP->url.c_str()[0] == '/')))
    {
        OrionError  error(SccBadRequest, "The Orion Context Broker is a REST service, not a 'web page'");
        std::string response = error.render(ciP->outFormat, "");

        LM_W(("Bad Input (The Orion Context Broker is a REST service, not a 'web page')"));
        restReply(ciP, response);

        return std::string("Empty URL");
    }

    ciP->httpStatusCode = SccOk;

    components = stringSplit(ciP->url, '/', compV);

    for (unsigned int ix = 0; serviceV[ix].treat != NULL; ++ix)
    {
        if ((serviceV[ix].components != 0) && (serviceV[ix].components != components))
        {
            continue;
        }

        if ((ciP->method != serviceV[ix].verb) && (serviceV[ix].verb != "*"))
        {
            continue;
        }

        strncpy(ciP->payloadWord, serviceV[ix].payloadWord.c_str(), sizeof(ciP->payloadWord));
        bool match = true;
        for (int compNo = 0; compNo < components; ++compNo)
        {
            if (serviceV[ix].compV[compNo] == "*")
            {
                continue;
            }

            if (strcasecmp(serviceV[ix].compV[compNo].c_str(), compV[compNo].c_str()) != 0)
            {
                match = false;
                break;
            }
        }

        if (match == false)
        {
            continue;
        }

        if ((ciP->payload != NULL) && (ciP->payloadSize != 0) && (ciP->payload[0] != 0) && (serviceV[ix].verb != "*"))
        {
            std::string response;

            LM_T(LmtParsedPayload, ("Parsing payload for URL '%s', method '%s', service vector index: %d", ciP->url.c_str(), ciP->method.c_str(), ix));
            ciP->parseDataP = &parseData;
            response = payloadParse(ciP, &parseData, &serviceV[ix], &reqP, &jsonReqP);
            LM_T(LmtParsedPayload, ("payloadParse returns '%s'", response.c_str()));

            if (response != "OK")
            {
                restReply(ciP, response);

                if (reqP != NULL)
                {
                    reqP->release(&parseData);
                }
                if (jsonReqP != NULL)
                {
                    jsonReqP->release(&parseData);
                }

                compV.clear();
                return response;
            }
        }

        LM_T(LmtService, ("Treating service %s %s", serviceV[ix].verb.c_str(), ciP->url.c_str())); // Sacred - used in 'heavyTest'
        statisticsUpdate(serviceV[ix].request, ciP->inFormat);

        // Tenant to connectionInfo
        ciP->tenant = ciP->tenantFromHttpHeader;

        //
        // A tenant string must not be longer than 50 characters and may only contain
        // underscores and alphanumeric characters.
        //
        std::string result;
        if ((ciP->tenant != "") && ((result = tenantCheck(ciP->tenant)) != "OK"))
        {
            OrionError  error(SccBadRequest,
                              "tenant name not accepted - a tenant string must not be longer than " MAX_TENANT_NAME_LEN_STRING " characters"
                              " and may only contain underscores and alphanumeric characters");

            std::string  response = error.render(ciP->outFormat, "");

            LM_W(("Bad Input (%s)", error.details.c_str()));
            restReply(ciP, response);

            if (reqP != NULL)
            {
                reqP->release(&parseData);
            }

            if (jsonReqP != NULL)
            {
                jsonReqP->release(&parseData);
            }

            compV.clear();

            return response;
        }

        LM_T(LmtTenant, ("tenant: '%s'", ciP->tenant.c_str()));
        commonFilters(ciP, &parseData, &serviceV[ix]);
        scopeFilter(ciP, &parseData, &serviceV[ix]);
        std::string response = serviceV[ix].treat(ciP, components, compV, &parseData);
        filterRelease(&parseData, serviceV[ix].request);

        if (reqP != NULL)
        {
            reqP->release(&parseData);
        }

        if (jsonReqP != NULL)
        {
            jsonReqP->release(&parseData);
        }

        compV.clear();

        if (response == "DIE")
        {
            orionExitFunction(0, "Received a 'DIE' request on REST interface");
        }

        restReply(ciP, response);
        return response;
    }

    LM_W(("Bad Input (service '%s' not recognized)", ciP->url.c_str()));
    ciP->httpStatusCode = SccBadRequest;
    std::string answer = restErrorReplyGet(ciP, ciP->outFormat, "", ciP->payloadWord, SccBadRequest, std::string("unrecognized request"));
    restReply(ciP, answer);

    compV.clear();
    return answer;
}