synapse 2.168.0__py311-none-any.whl → 2.170.0__py311-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of synapse might be problematic. Click here for more details.

Files changed (42) hide show
  1. synapse/cortex.py +99 -10
  2. synapse/datamodel.py +5 -0
  3. synapse/lib/agenda.py +3 -0
  4. synapse/lib/ast.py +70 -12
  5. synapse/lib/cell.py +83 -21
  6. synapse/lib/httpapi.py +3 -0
  7. synapse/lib/layer.py +75 -6
  8. synapse/lib/node.py +7 -0
  9. synapse/lib/snap.py +25 -5
  10. synapse/lib/storm.py +1 -1
  11. synapse/lib/stormlib/cortex.py +1 -1
  12. synapse/lib/stormlib/model.py +420 -1
  13. synapse/lib/stormtypes.py +68 -3
  14. synapse/lib/types.py +35 -0
  15. synapse/lib/version.py +2 -2
  16. synapse/lib/view.py +94 -24
  17. synapse/models/files.py +40 -0
  18. synapse/models/inet.py +8 -4
  19. synapse/models/infotech.py +355 -17
  20. synapse/tests/files/cpedata.json +525034 -0
  21. synapse/tests/test_cortex.py +99 -0
  22. synapse/tests/test_lib_agenda.py +17 -3
  23. synapse/tests/test_lib_ast.py +66 -0
  24. synapse/tests/test_lib_cell.py +133 -52
  25. synapse/tests/test_lib_layer.py +52 -1
  26. synapse/tests/test_lib_scrape.py +72 -71
  27. synapse/tests/test_lib_snap.py +16 -1
  28. synapse/tests/test_lib_storm.py +118 -0
  29. synapse/tests/test_lib_stormlib_cortex.py +27 -0
  30. synapse/tests/test_lib_stormlib_model.py +532 -0
  31. synapse/tests/test_lib_stormtypes.py +161 -14
  32. synapse/tests/test_lib_types.py +20 -0
  33. synapse/tests/test_lib_view.py +77 -0
  34. synapse/tests/test_model_files.py +51 -0
  35. synapse/tests/test_model_inet.py +63 -1
  36. synapse/tests/test_model_infotech.py +187 -26
  37. synapse/tests/utils.py +12 -0
  38. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/METADATA +1 -1
  39. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/RECORD +42 -41
  40. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/LICENSE +0 -0
  41. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/WHEEL +0 -0
  42. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/top_level.txt +0 -0
@@ -508,6 +508,77 @@ bad_uncs = [
508
508
 
509
509
  unc_paths = '\n'.join(good_uncs + bad_uncs)
510
510
 
511
+ cpedata = r'''GOOD DATA
512
+ cpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:target_hw:other
513
+ cpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:target_hw:tspace non matched word
514
+ cpe:2.3:a:*:*:*:*:*:*:*:*:*:*
515
+ cpe:2.3:h:*:*:*:*:*:*:*:*:*:*
516
+ cpe:2.3:o:*:*:*:*:*:*:*:*:*:*
517
+ cpe:2.3:-:*:*:*:*:*:*:*:*:*:*
518
+ cpe:2.3:*:*:*:*:*:*:*:*:*:*:*
519
+ cpe:2.3:*:-:na:*:*:*:*:*:*:*:*
520
+ cpe:2.3:*:.:dot:*:*:*:*:*:*:*:*
521
+ cpe:2.3:*:_:underscore:*:*:*:*:*:*:*:*
522
+
523
+ A few quoted characters
524
+ cpe:2.3:*:\!:quoted:*:*:*:*:*:*:*:*
525
+ cpe:2.3:*:\?:quoted:*:*:*:*:*:*:*:*
526
+ cpe:2.3:*:\*:quoted:*:*:*:*:*:*:*:*
527
+ cpe:2.3:*:\\:escapeescape:*:*:*:*:*:*:*:*
528
+ cpe:2.3:*:langtest:*:*:*:*:-:*:*:*:*
529
+ cpe:2.3:*:langtest:*:*:*:*:*:*:*:*:*
530
+ cpe:2.3:*:langtest:*:*:*:*:en:*:*:*:*
531
+ cpe:2.3:*:langtest:*:*:*:*:usa:*:*:*:*
532
+ cpe:2.3:*:langtest:*:*:*:*:usa-en:*:*:*:*
533
+ cpe:2.3:*:langtest:*:*:*:*:usa-123:*:*:*:*
534
+
535
+ A few examples
536
+ cpe:2.3:a:ntp:ntp:4.2.8:p3:*:*:*:*:*:*
537
+ cpe:2.3:o:microsoft:windows_7:-:sp2:*:*:*:*:*:*
538
+ cpe:2.3:a:hp:insight:7.4.0.1570:-:*:*:online:win2003:x64:*
539
+ cpe:2.3:a:foo\\bar:big\$money_2010:*:*:*:*:special:ipod_touch:80gb:*
540
+ cpe:2.3:a:hp:openview_network_manager:7.51:*:*:*:*:linux:*:*
541
+ cpe:2.3:a:apple:swiftnio_http\/2:1.19.1:*:*:*:*:swift:*:*
542
+
543
+ Some quoted examples
544
+ cpe:2.3:a:fooo:bar_baz\:_beep_bpp_sys:1.1:*:*:*:*:ios:*:*
545
+ cpe:2.3:a:lemonldap-ng:apache\:\:session\:\:browsable:0.9:*:*:*:*:perl:*:*
546
+ cpe:2.3:a:daemon-ng:hurray\:\::0.x:*:*:*:*:*:*:*
547
+ cpe:2.3:a:microsoft:intern\^et_explorer:8.0.6001:beta:*:*:*:*:*:*
548
+
549
+ TEXT examples
550
+ Example double quoted cpe value "cpe:2.3:a:vertex:synapse:*:*:*:*:*:*:*:dquotes".
551
+ Example double quoted cpe value "cpe:2.3:a:vertex:synapse:*:*:*:*:*:*:*:MiXeDcAsE".
552
+ Example single quoted cpe value "cpe:2.3:a:vertex:synapse:*:*:*:*:*:*:*:squotes".
553
+ A CPE at the end of a sentence like this captures the period... cpe:2.3:a:*:*:*:*:*:*:*:*:*:hasperiod.
554
+ Some CPE are exciting! Like this cpe:2.3:a:*:*:*:*:*:*:*:*:*:noexclaim!
555
+ Some CPE are boring! Like this cpe:2.3:a:*:*:*:*:*:*:*:*:*:noslash\
556
+ Unicode endings are omitted cpe:2.3:a:*:*:*:*:*:*:*:*:*:unicodeend0ॐ
557
+ Unicode quotes “cpe:2.3:a:*:*:*:*:*:*:*:*:*:smartquotes”
558
+ cpe:2.3:*:?why??:*:*:*:*:*:*:*:*:*
559
+ cpe:2.3:*:*why*:*:*:*:*:*:*:*:*:*
560
+
561
+ EMBEDDED TEXT
562
+ wordscpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:target_hw:otherxxx:newp
563
+ wordscpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:target_hw:otherzzz:
564
+
565
+ BAD values
566
+ cpe:2.3:*:?:spec1:*:*:*:*:*:*:*:*
567
+ cpe:2.3:a:vertex:synapse:*:*:*:NEWP:*:*:*:*
568
+ cpe:2.3:a::::::::::
569
+ cpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:ॐ:other
570
+ cpe:2.3:a:vendor:product:version:update:edition
571
+ cpe:2.3:a:opps:bad_quote\\/2:1.19.1:*:*:*:*:swift:*:*
572
+
573
+ # Bad languages
574
+ cpe:2.3:*:langtest:*:*:*:*:a:*:*:*:*
575
+ cpe:2.3:*:langtest:*:*:*:*:aaaa:*:*:*:*
576
+ cpe:2.3:*:langtest:*:*:*:*:usa-o:*:*:*:*
577
+ cpe:2.3:*:langtest:*:*:*:*:usa-omn:*:*:*:*
578
+ cpe:2.3:*:langtest:*:*:*:*:usa-12:*:*:*:*
579
+ cpe:2.3:*:langtest:*:*:*:*:usa-1234:*:*:*:*
580
+ '''
581
+
511
582
  class ScrapeTest(s_t_utils.SynTest):
512
583
 
513
584
  def test_scrape_basic(self):
@@ -1050,77 +1121,7 @@ class ScrapeTest(s_t_utils.SynTest):
1050
1121
  self.eq(erv, fv)
1051
1122
 
1052
1123
  def test_scrape_cpe(self):
1053
- cpedata = r'''
1054
- GOOD DATA
1055
- cpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:target_hw:other
1056
- cpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:target_hw:tspace non matched word
1057
- cpe:2.3:a:*:*:*:*:*:*:*:*:*:*
1058
- cpe:2.3:h:*:*:*:*:*:*:*:*:*:*
1059
- cpe:2.3:o:*:*:*:*:*:*:*:*:*:*
1060
- cpe:2.3:-:*:*:*:*:*:*:*:*:*:*
1061
- cpe:2.3:*:*:*:*:*:*:*:*:*:*:*
1062
- cpe:2.3:*:-:na:*:*:*:*:*:*:*:*
1063
- cpe:2.3:*:.:dot:*:*:*:*:*:*:*:*
1064
- cpe:2.3:*:_:underscore:*:*:*:*:*:*:*:*
1065
-
1066
- A few quoted characters
1067
- cpe:2.3:*:\!:quoted:*:*:*:*:*:*:*:*
1068
- cpe:2.3:*:\?:quoted:*:*:*:*:*:*:*:*
1069
- cpe:2.3:*:\*:quoted:*:*:*:*:*:*:*:*
1070
- cpe:2.3:*:\\:escapeescape:*:*:*:*:*:*:*:*
1071
- cpe:2.3:*:langtest:*:*:*:*:-:*:*:*:*
1072
- cpe:2.3:*:langtest:*:*:*:*:*:*:*:*:*
1073
- cpe:2.3:*:langtest:*:*:*:*:en:*:*:*:*
1074
- cpe:2.3:*:langtest:*:*:*:*:usa:*:*:*:*
1075
- cpe:2.3:*:langtest:*:*:*:*:usa-en:*:*:*:*
1076
- cpe:2.3:*:langtest:*:*:*:*:usa-123:*:*:*:*
1077
-
1078
- A few examples
1079
- cpe:2.3:a:ntp:ntp:4.2.8:p3:*:*:*:*:*:*
1080
- cpe:2.3:o:microsoft:windows_7:-:sp2:*:*:*:*:*:*
1081
- cpe:2.3:a:hp:insight:7.4.0.1570:-:*:*:online:win2003:x64:*
1082
- cpe:2.3:a:foo\\bar:big\$money_2010:*:*:*:*:special:ipod_touch:80gb:*
1083
- cpe:2.3:a:hp:openview_network_manager:7.51:*:*:*:*:linux:*:*
1084
- cpe:2.3:a:apple:swiftnio_http\/2:1.19.1:*:*:*:*:swift:*:*
1085
-
1086
- Some quoted examples
1087
- cpe:2.3:a:fooo:bar_baz\:_beep_bpp_sys:1.1:*:*:*:*:ios:*:*
1088
- cpe:2.3:a:lemonldap-ng:apache\:\:session\:\:browsable:0.9:*:*:*:*:perl:*:*
1089
- cpe:2.3:a:daemon-ng:hurray\:\::0.x:*:*:*:*:*:*:*
1090
- cpe:2.3:a:microsoft:intern\^et_explorer:8.0.6001:beta:*:*:*:*:*:*
1091
-
1092
- TEXT examples
1093
- Example double quoted cpe value "cpe:2.3:a:vertex:synapse:*:*:*:*:*:*:*:dquotes".
1094
- Example double quoted cpe value "cpe:2.3:a:vertex:synapse:*:*:*:*:*:*:*:MiXeDcAsE".
1095
- Example single quoted cpe value "cpe:2.3:a:vertex:synapse:*:*:*:*:*:*:*:squotes".
1096
- A CPE at the end of a sentence like this captures the period... cpe:2.3:a:*:*:*:*:*:*:*:*:*:hasperiod.
1097
- Some CPE are exciting! Like this cpe:2.3:a:*:*:*:*:*:*:*:*:*:noexclaim!
1098
- Some CPE are boring! Like this cpe:2.3:a:*:*:*:*:*:*:*:*:*:noslash\
1099
- Unicode endings are omitted cpe:2.3:a:*:*:*:*:*:*:*:*:*:unicodeend0ॐ
1100
- Unicode quotes “cpe:2.3:a:*:*:*:*:*:*:*:*:*:smartquotes”
1101
- cpe:2.3:*:?why??:*:*:*:*:*:*:*:*:*
1102
- cpe:2.3:*:*why*:*:*:*:*:*:*:*:*:*
1103
-
1104
- EMBEDDED TEXT
1105
- wordscpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:target_hw:otherxxx:newp
1106
- wordscpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:target_hw:otherzzz:
1107
-
1108
- BAD values
1109
- cpe:2.3:*:?:spec1:*:*:*:*:*:*:*:*
1110
- cpe:2.3:a:vertex:synapse:*:*:*:NEWP:*:*:*:*
1111
- cpe:2.3:a::::::::::
1112
- cpe:2.3:a:vendor:product:version:update:edition:lng:sw_edition:target_sw:ॐ:other
1113
- cpe:2.3:a:vendor:product:version:update:edition
1114
- cpe:2.3:a:opps:bad_quote\\/2:1.19.1:*:*:*:*:swift:*:*
1115
-
1116
- # Bad languages
1117
- cpe:2.3:*:langtest:*:*:*:*:a:*:*:*:*
1118
- cpe:2.3:*:langtest:*:*:*:*:aaaa:*:*:*:*
1119
- cpe:2.3:*:langtest:*:*:*:*:usa-o:*:*:*:*
1120
- cpe:2.3:*:langtest:*:*:*:*:usa-omn:*:*:*:*
1121
- cpe:2.3:*:langtest:*:*:*:*:usa-12:*:*:*:*
1122
- cpe:2.3:*:langtest:*:*:*:*:usa-1234:*:*:*:*
1123
- '''
1124
+
1124
1125
  nodes = sorted(set(s_scrape.scrape(cpedata, ptype='it:sec:cpe')))
1125
1126
  nodes.remove(('it:sec:cpe', 'cpe:2.3:*:*:*:*:*:*:*:*:*:*:*'))
1126
1127
  nodes.remove(('it:sec:cpe', 'cpe:2.3:*:-:na:*:*:*:*:*:*:*:*'))
@@ -584,7 +584,10 @@ class SnapTest(s_t_utils.SynTest):
584
584
  async def test_snap_editor(self):
585
585
 
586
586
  async with self.getTestCore() as core:
587
- nodes = await core.nodes('[ media:news=63381924986159aff183f0c85bd8ebad +(refs)> {[ inet:fqdn=vertex.link ]} ]')
587
+
588
+ await core.nodes('$lib.model.ext.addTagProp(test, (str, ({})), ({}))')
589
+ await core.nodes('[ media:news=63381924986159aff183f0c85bd8ebad +(refs)> {[ inet:fqdn=vertex.link ]} +#foo ]')
590
+
588
591
  root = core.auth.rootuser
589
592
  async with await core.view.snap(user=root) as snap:
590
593
  async with snap.getEditor() as editor:
@@ -608,6 +611,14 @@ class SnapTest(s_t_utils.SynTest):
608
611
  self.len(1, nodeedits)
609
612
  self.len(1, nodeedits[0][2])
610
613
 
614
+ self.false(await news.hasData('foo'))
615
+ await news.setData('foo', 'bar')
616
+ self.true(await news.hasData('foo'))
617
+
618
+ self.false(news.hasTagProp('foo', 'test'))
619
+ await news.setTagProp('foo', 'test', 'bar')
620
+ self.true(news.hasTagProp('foo', 'test'))
621
+
611
622
  async with snap.getEditor() as editor:
612
623
  news = await editor.addNode('media:news', '63381924986159aff183f0c85bd8ebad')
613
624
 
@@ -629,6 +640,10 @@ class SnapTest(s_t_utils.SynTest):
629
640
  self.false(await news.delEdge('pwns', 1))
630
641
  self.false(await news.delEdge('pwns', 'bar'))
631
642
 
643
+ self.true(await news.hasData('foo'))
644
+
645
+ self.true(news.hasTagProp('foo', 'test'))
646
+
632
647
  self.len(1, await core.nodes('media:news -(pwns)> *'))
633
648
 
634
649
  self.len(1, await core.nodes('[ test:ro=foo :writeable=hehe :readable=haha ]'))
@@ -19,6 +19,8 @@ import synapse.lib.version as s_version
19
19
  import synapse.tests.utils as s_t_utils
20
20
  from synapse.tests.utils import alist
21
21
 
22
+ import synapse.tools.backup as s_tools_backup
23
+
22
24
  class StormTest(s_t_utils.SynTest):
23
25
 
24
26
  async def test_lib_storm_jsonexpr(self):
@@ -2041,6 +2043,90 @@ class StormTest(s_t_utils.SynTest):
2041
2043
 
2042
2044
  self.eq((1, 6), await core.callStorm('return($lib.queue.gen(foo).get(1))'))
2043
2045
 
2046
+ async def test_storm_dmon_query_state(self):
2047
+ with self.getTestDir() as dirn:
2048
+ dirn00 = s_common.gendir(dirn, 'core00')
2049
+ dirn01 = s_common.gendir(dirn, 'core01')
2050
+ dirn02 = s_common.gendir(dirn, 'core02')
2051
+
2052
+ async with self.getTestCore(dirn=dirn00) as core00:
2053
+
2054
+ msgs = await core00.stormlist('[ inet:ipv4=1.2.3.4 ]')
2055
+ self.stormHasNoWarnErr(msgs)
2056
+
2057
+ s_tools_backup.backup(dirn00, dirn01)
2058
+ s_tools_backup.backup(dirn00, dirn02)
2059
+
2060
+ async with self.getTestCore(dirn=dirn00) as core00:
2061
+ conf01 = {'mirror': core00.getLocalUrl()}
2062
+
2063
+ async with self.getTestCore(dirn=dirn01, conf=conf01) as core01:
2064
+
2065
+ conf02 = {'mirror': core01.getLocalUrl()}
2066
+
2067
+ async with self.getTestCore(dirn=dirn02, conf=conf02) as core02:
2068
+
2069
+ await core02.sync()
2070
+
2071
+ nodes = await core01.nodes('inet:ipv4')
2072
+ self.len(1, nodes)
2073
+ self.eq(nodes[0].ndef, ('inet:ipv4', 16909060))
2074
+
2075
+ q = '''
2076
+ $lib.queue.gen(dmonloop)
2077
+ return(
2078
+ $lib.dmon.add(${
2079
+ $queue = $lib.queue.get(dmonloop)
2080
+ while $lib.true {
2081
+ ($offs, $mesg) = $queue.get()
2082
+
2083
+ switch $mesg.0 {
2084
+ "print": { $lib.print($mesg.1) }
2085
+ "warn": { $lib.warn($mesg.1) }
2086
+ "leave": {
2087
+ $lib.print(leaving)
2088
+ break
2089
+ }
2090
+ *: { continue }
2091
+ }
2092
+
2093
+ $queue.cull($offs)
2094
+ }
2095
+ }, name=dmonloop)
2096
+ )
2097
+ '''
2098
+ ddef = await core02.callStorm(q)
2099
+ self.nn(ddef['iden'])
2100
+
2101
+ dmons = await core02.getStormDmons()
2102
+ self.len(1, dmons)
2103
+ self.eq(dmons[0]['iden'], ddef['iden'])
2104
+
2105
+ info = await core02.getStormDmon(ddef['iden'])
2106
+ self.eq(info['iden'], ddef['iden'])
2107
+ self.eq(info['name'], 'dmonloop')
2108
+ self.eq(info['status'], 'running')
2109
+
2110
+ await core02.callStorm('$lib.queue.get(dmonloop).put((print, printfoo))')
2111
+ await core02.callStorm('$lib.queue.get(dmonloop).put((warn, warnfoo))')
2112
+
2113
+ info = await core02.getStormDmon(ddef['iden'])
2114
+ self.eq(info['status'], 'running')
2115
+
2116
+ logs = await core02.getStormDmonLog(ddef['iden'])
2117
+ msgs = [k[1] for k in logs]
2118
+ self.stormIsInPrint('printfoo', msgs)
2119
+ self.stormIsInWarn('warnfoo', msgs)
2120
+
2121
+ await core02.callStorm('$lib.queue.get(dmonloop).put((leave,))')
2122
+
2123
+ info = await core02.getStormDmon(ddef['iden'])
2124
+ self.eq(info['status'], 'sleeping')
2125
+
2126
+ logs = await core02.getStormDmonLog(ddef['iden'])
2127
+ msgs = [k[1] for k in logs]
2128
+ self.stormIsInPrint('leaving', msgs)
2129
+
2044
2130
  async def test_storm_pipe(self):
2045
2131
 
2046
2132
  async with self.getTestCore() as core:
@@ -3098,6 +3184,38 @@ class StormTest(s_t_utils.SynTest):
3098
3184
  nodes = await core.nodes(q, opts={'view': fork, 'vars': {'view': view}})
3099
3185
  self.len(1, nodes)
3100
3186
 
3187
+ async def test_storm_viewexec(self):
3188
+
3189
+ async with self.getTestCore() as core:
3190
+
3191
+ view = await core.callStorm('return( $lib.view.get().iden )')
3192
+ fork = await core.callStorm('return( $lib.view.get().fork().iden )')
3193
+
3194
+ await core.addStormPkg({
3195
+ 'name': 'testpkg',
3196
+ 'version': (0, 0, 1),
3197
+ 'modules': (
3198
+ {'name': 'priv.exec',
3199
+ 'asroot:perms': [['power-ups', 'testpkg']],
3200
+ 'modconf': {'viewiden': fork},
3201
+ 'storm': '''
3202
+ function asroot () {
3203
+ view.exec $modconf.viewiden { $foo=bar } | return($foo)
3204
+ }
3205
+ '''},
3206
+ ),
3207
+ })
3208
+
3209
+ visi = await core.auth.addUser('visi')
3210
+ asvisi = {'user': visi.iden}
3211
+
3212
+ await core.stormlist('auth.user.addrule visi power-ups.testpkg')
3213
+
3214
+ with self.raises(s_exc.AuthDeny):
3215
+ await core.callStorm('return(woot)', opts={'user': visi.iden, 'view': fork})
3216
+
3217
+ self.eq('bar', await core.callStorm('return($lib.import(priv.exec).asroot())', opts=asvisi))
3218
+
3101
3219
  async def test_storm_argv_parser(self):
3102
3220
 
3103
3221
  pars = s_storm.Parser(prog='hehe')
@@ -281,6 +281,18 @@ $request.reply(206, headers=$headers, body=({"no":"body"}))
281
281
  self.eq(data.get('json'), 'err')
282
282
  self.eq(data.get('path'), 'echo/words/wOw')
283
283
 
284
+ # Storm query logging includes the httpapi iden in structlog data
285
+ core.stormlog = True
286
+ with self.getStructuredAsyncLoggerStream('synapse.storm', 'Executing storm query') as stream:
287
+ resp = await sess.get(url)
288
+ self.eq(resp.status, 200)
289
+ self.true(await stream.wait(timeout=12))
290
+ data = stream.getvalue()
291
+ raw_mesgs = [m for m in data.split('\n') if m]
292
+ msgs = [json.loads(m) for m in raw_mesgs]
293
+ self.eq(msgs[0].get('httpapi'), echoiden)
294
+ core.stormlog = False
295
+
284
296
  # Sad paths on the $request methods
285
297
  q = '''$api = $lib.cortex.httpapi.add(testpath02)
286
298
  $api.methods.get = ${ $request.sendcode(200) $request.sendheaders('beep beep') }
@@ -1268,6 +1280,12 @@ for $i in $values {
1268
1280
  return ( ($api.iden) )'''
1269
1281
  iden06 = await core.callStorm(q)
1270
1282
 
1283
+ # attempt to JSON decode non-JSON request
1284
+ q = '''$api = $lib.cortex.httpapi.add(bad07)
1285
+ $api.methods.get = ${ $foo = $request.json() }
1286
+ return ( ($api.iden) )'''
1287
+ iden07 = await core.callStorm(q)
1288
+
1271
1289
  async with self.getHttpSess(auth=('root', 'root'), port=hport) as sess:
1272
1290
  resp = await sess.get(f'https://localhost:{hport}/api/ext/bad00')
1273
1291
  self.eq(resp.status, 500)
@@ -1317,6 +1335,15 @@ for $i in $values {
1317
1335
  self.eq(resp.status, 201)
1318
1336
  self.eq(await resp.json(), {})
1319
1337
 
1338
+ with self.getAsyncLoggerStream('synapse.lib.httpapi',
1339
+ f'Error executing Extended HTTP API {iden07}: StormRuntimeError') as stream:
1340
+ resp = await sess.get(f'https://localhost:{hport}/api/ext/bad07')
1341
+ self.true(await stream.wait(timeout=6))
1342
+ self.eq(resp.status, 500)
1343
+ data = await resp.json()
1344
+ self.eq(data.get('code'), 'StormRuntimeError')
1345
+ self.isin('Failed to decode request body as JSON: Expecting value', data.get('mesg'))
1346
+
1320
1347
  async def test_cortex_httpapi_dynamic(self):
1321
1348
 
1322
1349
  # API endpoints can be dynamic. Use at your own risk.