Alex.B: Symfony 5 Routing mit Defaults

Hallo Leute,

eine REST App nimmt ein PUT-Request entgegen. Dieser beinhaltet einen Unix-Timestamp.

Nun möchte ich diesen Parameter gerne optional machen. Wird ein Timestamp übergeben, soll dieser anhand der hinterlegten Regeln validiert werden. Wird kein Timestamp übergeben, soll die App eins erzeugen.

# testing
"PUT /tracking/123456789" erzeugt einen Fehler da nur 9 Zeichen
"PUT /tracking/12345678901234" erzeugt einen Fehler da nur >13 Zeichen
"PUT /tracking/1234567890" klappt

Nun soll folgender Request auch funktionieren
"PUT /tracking/"

In diesem Fall sollte Symfony den "default timestamp" mit dem Wert "0" nehmen. Klappt aber nicht. Es gibt eine Fehlermeldung "No route found for "PUT /tracking/"

Hoffentlich könnt ihr mir helfen, eigentlich ganz easy^^

# routing
api_add_entry:
    path: /tracking/{!timestamp}
    controller: App\Controller\MainController::addEntry
    defaults:
        timestamp: 0
    requirements:
        timestamp: '\d+'
    methods: [PUT]
# validation
App\Usecase\AddEntity\AddEntityRequest:
  properties:
    timestamp:
      - Length:
          min: 10
          max: 13
  1. Wird kein Timestamp übergeben, soll die App eins erzeugen.

    Na dann prüf mal Deine Validationsbedingungen. min: 10 past nicht so recht zu Deinem Vorhaben.

    Viel Erfolg

    1. Hallo pl,

      stimmt wohl, ein solcher constraint ist zu doof für die Anforderung.

      Man könnte es über die requirements regex lösen, oder mit einem Callback- oder Expression-Constraint.

      Rolf

      --
      sumpsi - posui - clusi
      1. he @Rolf B

        Wie so schreibst Du mir das? Ich hab mit Symfony nix am Hut, die machen das viel zu kompliziert. Aber wenn Du mich schon so anscheibst, bei mir wäre da eine statische Route zu konfigurieren und für die Verarbeitung ein Trait oder eine Klasse zu schreiben, fertig.

        MFG

        1. Hallo pl,

          Wie so schreibst Du mir das?

          Vermutlich weil du hier im Thread geantwortet hast 🙄

          Freundliche Grüße,
          Christian Kruse

    2. Hallo pl,

      ja passt nicht, aber selbst mit einem passenden Default geht es nicht. Die Route wird nicht gefunden.

      Oder muss der ngnix dahingehend abgepasst werden?

      #nginx config
      server {
          listen 80;
          server_tokens off;
      
          root /var/www/html/public;
          index index.php;
      
          charset utf-8;
      
          error_log  /var/log/nginx/error.log;
          access_log /var/log/nginx/access.log;
      
          location / {
                  try_files $uri $uri/ /index.php?$args;
                  include fastcgi_params;
      
                  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                  fastcgi_pass php-timetrackerservice:9000;
                  fastcgi_index index.php;
                  fastcgi_cache off;
                  fastcgi_hide_header X-Powered-By;
      
                  # basics
                  add_header Accept "application/json" always;
                  add_header Accept-Charset "utf-8" always;
      
                  # security
                  add_header X-XSS-Protection "1; mode=block" always;
                  add_header X-Frame-Options "SAMEORIGIN" always;
                  add_header X-Content-Type-Options "nosniff" always;
                  add_header Strict-Transport-Security "max-age=31536000" always;
                  add_header Content-Security-Policy "default-src 'self';" always;
                  add_header Referrer-Policy "no-referrer" always;
                  add_header X-Permitted-Cross-Domain-Policies "none" always;
                  add_header Feature-Policy "none" always;
          }
      }
      
      1. Hallo Alex.B,

        da ein PUT mit timestamp akzeptiert wird, sollte es nicht an der Webserverkonfiguration liegen.

        Probier's doch mal so:

        api_add_entry:
            path: /tracking/{!timestamp}
            controller: App\Controller\MainController::addEntry
            requirements:
                timestamp: '\d+'
            methods: [PUT]
        
        api_add_defaultentry:
            path: /tracking
            controller: App\Controller\MainController::addDefaultEntry
            methods: [PUT]
        

        und im Controller fügst Du eine neue Methode addDefaultEntry ein, die einen Timestamp vergibt und damit addEntry aufruft.

        Wenn Du es unbedingt mit einer einzigen Route lösen willst, muss vermutlich das Requirement ganz weg oder durch \d* ersetzt werden. Die Kollision mit dem Constraint gibt es dann aber immer noch. Der will ja was mindestens 10-stelliges sehen. Ich weiß allerdings nicht wann der Constraint greift - diese add\usecase Konfiguration finde ich nirgends in der Doku. Was ist das?

        Rolf

        --
        sumpsi - posui - clusi
      2. Oder muss der ngnix dahingehend abgepasst werden?

        Nein. Betrachte Deine Route als eine Route mit statischen Anteil /tracking und einem Parameter {timestamp}. Zum Validieren Letzterem eignet sich eine Regex \d{0,13} bzw. ^\d{0,13}$ (mit Anker) welche die Bedingung beschreibt, daß für timestamp 0..13 Ziffern zulässig sind.

        Das wäre einmal die Prüfung. Erst wenn sich dabei eine Stringlänge von 0 ergibt, kommt der Default ins Spiel.

        MFG