Repository: cmu-delphi/delphi-epidata
Issue: `signal:*` queries return a 504 Gateway Error

These queries should return the data for all the signals  in each data source, but instead they spin until a 504 Gateway Error

```
https://api.covidcast.cmu.edu/epidata/covidcast/?signal=usa-facts:*&time=day:20220104&geo_type=state&geo_values=ca
https://api.covidcast.cmu.edu/epidata/covidcast/?signal=jhu-csse:*&time=day:20220104&geo_type=state&geo_values=ca
https://api.covidcast.cmu.edu/epidata/covidcast/?signal=safegraph:*&time=day:20220104&geo_type=state&geo_values=ca
```

You can confirm that at least one signal has data for each of these with
```
https://api.covidcast.cmu.edu/epidata/covidcast/?signal=usa-facts:confirmed_cumulative_num&time=day:20220104&geo_type=state&geo_values=ca
https://api.covidcast.cmu.edu/epidata/covidcast/?signal=jhu-csse:confirmed_cumulative_num&time=day:20220104&geo_type=state&geo_values=ca
https://api.covidcast.cmu.edu/epidata/covidcast/?signal=safegraph:bars_visit_num&time=day:20220104&geo_type=state&geo_values=ca
```

Possibly a bug with the `signal:*` handling?

Changed files:
src/server/endpoints/covidcast.py, integrations/server/test_covidcast.py

diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py
index 86ce0c53..3de69f02 100644
--- a/integrations/server/test_covidcast.py
+++ b/integrations/server/test_covidcast.py
@@ -63,6 +63,18 @@ class CovidcastTests(CovidcastBase):
     self._insert_rows(rows)
     return rows
 
+  def _insert_placeholder_set_four(self):
+    rows = [
+      self._make_placeholder_row(source='src1', signal=str(i)*5, value=i*1., stderr=i*10., sample_size=i*100.)[0]
+      for i in [1, 2, 3]
+    ] + [
+      # signal intended to overlap with the signal above
+      self._make_placeholder_row(source='src2', signal=str(i-3)*5, value=i*1., stderr=i*10., sample_size=i*100.)[0]
+      for i in [4, 5, 6]
+    ]
+    self._insert_rows(rows)
+    return rows 
+
   def test_round_trip(self):
     """Make a simple round-trip with some sample data."""
 
@@ -225,6 +237,26 @@ class CovidcastTests(CovidcastBase):
       'message': 'success',
     })
 
+  def test_signal_wildcard(self):
+    """Select all signals with a wildcard query."""
+
+    # insert placeholder data
+    rows = self._insert_placeholder_set_four()
+    expected_signals = [
+      self.expected_from_row(r) for r in rows[:3]
+    ]
+
+    # make the request
+    response, _ = self.request_based_on_row(rows[0], signals="*")
+
+    self.maxDiff = None
+    # assert that the right data came back
+    self.assertEqual(response, {
+      'result': 1,
+      'epidata': expected_signals,
+      'message': 'success',
+    })
+
   def test_geo_value(self):
     """test different variants of geo types: single, *, multi."""
 
diff --git a/src/server/endpoints/covidcast.py b/src/server/endpoints/covidcast.py
index fedb1959..9211a0d6 100644
--- a/src/server/endpoints/covidcast.py
+++ b/src/server/endpoints/covidcast.py
@@ -49,8 +49,10 @@ def parse_source_signal_pairs() -> List[SourceSignalPair]:
     ds = request.values.get("data_source")
     if ds:
         # old version
-        require_any("signal", "signals")
+        require_any("signal", "signals", empty=True)
         signals = extract_strings(("signals", "signal"))
+        if len(signals) == 1 and signals[0] == "*":
+            return [SourceSignalPair(ds, True)]
         return [SourceSignalPair(ds, signals)]
 
     if ":" not in request.values.get("signal", ""):