Browse Source
			 
			
			httpcaddyfile: support matching headers that do not exist (#3909 ) 
 
* add integration test for null header matcher
* implement null header matcher syntax
* avoid repeating magic !
* check for field following ! character 
			
			
				 
		
			
				
					
						Jack Baron 
					
					5 years ago 
							GitHub 
							
						 
					
				 
				
			 
		 
		
			
				
					GPG Key ID:  
		
		
		
	
		
			
				 2 changed files  with 
48 additions  and 
5 deletions 
			 
			
		 
		
			
				
					
					
					  
					caddytest/integration/caddyfile_adapt/matcher_syntax.txt 
				 
			
				
					
					
					  
					modules/caddyhttp/matchers.go 
				 
			
		 
		
			
			
			
			
			
			
				
				
					
						
							
								
									
	
		
			
				
					
						
						
							
								 
						
						
					 
				
				@ -31,6 +31,12 @@ 
			
		
	
		
			
				
							query bar=baz 
			
		
	
		
			
				
						} 
			
		
	
		
			
				
						respond @matcher8 "query matcher merging pairs with the same keys" 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						@matcher9 { 
			
		
	
		
			
				
							header !Foo 
			
		
	
		
			
				
							header Bar foo 
			
		
	
		
			
				
						} 
			
		
	
		
			
				
						respond @matcher9 "header matcher with null field matcher" 
			
		
	
		
			
				
					} 
			
		
	
		
			
				
					---------- 
			
		
	
		
			
				
					{ 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -183,6 +189,24 @@ 
			
		
	
		
			
				
														"handler": "static_response" 
			
		
	
		
			
				
													} 
			
		
	
		
			
				
												] 
			
		
	
		
			
				
											}, 
			
		
	
		
			
				
											{ 
			
		
	
		
			
				
												"match": [ 
			
		
	
		
			
				
													{ 
			
		
	
		
			
				
														"header": { 
			
		
	
		
			
				
															"Bar": [ 
			
		
	
		
			
				
																"foo" 
			
		
	
		
			
				
															], 
			
		
	
		
			
				
															"Foo": null 
			
		
	
		
			
				
														} 
			
		
	
		
			
				
													} 
			
		
	
		
			
				
												], 
			
		
	
		
			
				
												"handle": [ 
			
		
	
		
			
				
													{ 
			
		
	
		
			
				
														"body": "header matcher with null field matcher", 
			
		
	
		
			
				
														"handler": "static_response" 
			
		
	
		
			
				
													} 
			
		
	
		
			
				
												] 
			
		
	
		
			
				
											} 
			
		
	
		
			
				
										] 
			
		
	
		
			
				
									} 
			
		
	
	
		
			
				
					
						
							
								 
						
						
						
					 
				
				 
			
		
	
								
							
						
					 
					
				 
			 
		
			
			
			
			
			
			
				
				
					
						
							
								
									
	
		
			
				
					
						
						
							
								 
						
						
					 
				
				@ -470,13 +470,32 @@ func (m *MatchHeader) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { 
			
		
	
		
			
				
						}  
			
		
	
		
			
				
						for  d . Next ( )  {  
			
		
	
		
			
				
							var  field ,  val  string  
			
		
	
		
			
				
							if  ! d . Args ( & field ,  & val )  {  
			
		
	
		
			
				
								return  d . Errf ( "malformed header matcher: expected both  field and value " )  
			
		
	
		
			
				
							if  ! d . Args ( & field )  {  
			
		
	
		
			
				
								return  d . Errf ( "malformed header matcher: expected field" )  
			
		
	
		
			
				
							}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
							// If multiple header matchers with the same header field are defined,
  
			
		
	
		
			
				
							// we want to add the existing to the list of headers (will be OR'ed)
  
			
		
	
		
			
				
							http . Header ( * m ) . Add ( field ,  val )  
			
		
	
		
			
				
							if  strings . HasPrefix ( field ,  "!" )  {  
			
		
	
		
			
				
								if  len ( field )  ==  1  {  
			
		
	
		
			
				
									return  d . Errf ( "malformed header matcher: must have field name following ! character" )  
			
		
	
		
			
				
								}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
								field  =  field [ 1 : ]  
			
		
	
		
			
				
								headers  :=  * m  
			
		
	
		
			
				
								headers [ field ]  =  nil  
			
		
	
		
			
				
								m  =  & headers  
			
		
	
		
			
				
								if  d . NextArg ( )  {  
			
		
	
		
			
				
									return  d . Errf ( "malformed header matcher: null matching headers cannot have a field value" )  
			
		
	
		
			
				
								}  
			
		
	
		
			
				
							}  else  {  
			
		
	
		
			
				
								if  ! d . NextArg ( )  {  
			
		
	
		
			
				
									return  d . Errf ( "malformed header matcher: expected both field and value" )  
			
		
	
		
			
				
								}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
								// If multiple header matchers with the same header field are defined,
  
			
		
	
		
			
				
								// we want to add the existing to the list of headers (will be OR'ed)
  
			
		
	
		
			
				
								val  =  d . Val ( )  
			
		
	
		
			
				
								http . Header ( * m ) . Add ( field ,  val )  
			
		
	
		
			
				
							}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
							if  d . NextBlock ( 0 )  {  
			
		
	
		
			
				
								return  d . Err ( "malformed header matcher: blocks are not supported" )